I am attempting to use Moles to test a non-static method in a separate assembly. When running the test without the [HostType("Moles")] tag, the test runs fine. When I replace it I receive the following error:
"The type initializer for 'HtmlAgilityPack.HtmlNode' threw an exception."
I have attached code samples that perform in an identical manner.
Any help would be great!
Class/method being called by the unit test
using System;
using HtmlAgilityPack;
using System.Web;
namespace HAPAndMoles
{
public class Class1
{
public void fooBar()
{
HtmlDocument foo = new HtmlDocument();
}
}
}
Unit Test
using System;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using HAPAndMoles;
using Microsoft.Moles.Framework;
using HtmlAgilityPack;
using System.Web;
namespace HAPAndMoles
{
[TestClass]
public class UnitTest1
{
[TestMethod]
[HostType("Moles")]
public void TestMethod1()
{
Class1 bar = new Class1();
bar.fooBar();
}
}
}
I'm not sure I understand your example because in fact you don't use Moles.
If you just want to "Mole" our own non-virtual method, in the references of your test project you just have to right-click on the assembly of the tested project and choose Add Moles Assembly. That will create an HAPAndMoles.Moles reference.
Then add the corresponding using and you can call your class "moled" starting with M (Class1 => MCLass1). I show you an example testing the MClass1 behaviour:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using HAPAndMoles;
using HAPAndMoles.Moles;
namespace HAPAndMoles {
[TestClass]
public class UnitTest1
{
[TestMethod]
[HostType("Moles")]
public void TestMethod1()
{
bool called = false;
var bar = new MClass1()
{
fooBar = () => called = true
};
((Class1)bar).fooBar();
Assert.IsTrue(called);
}
}
}
When I want Moles of mscorlib, I right-click directly on the references of the test project and I can Add Moles Assembly for mscorlib. Then the
using Microsoft.Moles.Framework;
is needed.
Related
I have an error in the following code when using the Headers property:
Public Function UploadImage(image As String) As String
Dim wc As System.WebClient
'create WebClient
Set wc = CreateObject("System.Net.WebClient")
Call wc.Headers.Add("Authorization", "Client-ID " & ClientId) <------- Error occurs here
I have repro'd your issue as far as possible. You didn't mention what the error you were getting was, but I got:
Automation error -2146233079 (80131509)
I tried using
CallByName(wc, "Headers", VbGet)
... but that just returns
Automation error 440.
Oh well...
I looked up online, and found this link. My guess is that because the base class of the WebHeaderCollection class is not COM Visible, this causes the error.
My work-around would be to wrap up this functionality in a small .NET component, and make that COM visible.
An example of this would be something like:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
namespace WebClientWrapper
{
[ComVisible(true)]
[Guid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]
public class WebClientWrapper : WebClient
{
[ComVisible(true)]
public WebHeaderCollectionWrapper WHeaders
{
get
{
return new WebHeaderCollectionWrapper(base.Headers);
}
}
}
[ComVisible(true)]
[Guid("yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy")]
public class WebHeaderCollectionWrapper
{
WebHeaderCollection _whc;
internal WebHeaderCollectionWrapper(WebHeaderCollection whc)
{
_whc = whc;
}
[ComVisible(true)]
public void Add(string name, string value)
{
_whc.Add(name, value);
}
[ComVisible(true)]
public void Clear()
{
_whc.Clear();
}
}
}
(You will have to replace the GUIDs with your own values - use GUIDGEN.EXE).
Instantiate this component with CreateObject("WebClientWrapper.WebClientWrapper")
Now you would simply replace references to the Headers property to WHeaders (or whatever you want to call it). WHeaders gives you a true wrapper around WebHeaderCollection - you'll have to define all the other wrapped methods and properties yourself. I was hoping to define WHeaders as public WebHeaderCollectionWrapper, but that didn't seem to work.
Since WebClientWrapper inherits from WebClient, you should be able to use most of the properties and methods. Where you have troubles, just add new methods to the class wrapping up the functionality that doesn't work with VB.
Oh, and do remember to set the checkbox at Project Properties => Build => Output => Register for COM interop. And then reference the type library created.
I'm mucking about with reactive extensions and Iv'e hit a snag that I can't for the life of me work out what the cause is.
If I use a .NET 4 console mode app, where everything is static as follows:
using System;
using System.Reactive.Subjects;
using FakeDal;
using FakeDal.Entites;
using RxProducer;
namespace Runner
{
class Program
{
private static readonly Subject<DaftFrog> _subject = new Subject<DaftFrog>();
private static readonly Repository<DaftFrog> _frogRepo = new Repository<DaftFrog>();
static void Main()
{
_subject.Subscribe(RespondToNewData);
}
private static void RespondToNewData(DaftFrog frog)
{
_frogRepo.Save(frog);
}
}
}
DaftFrog is just a test class in my fake DAL class, this is a simple .NET 4 Class library project, the DaftFrog class, is a simple poco with a few fields in, the dal.save method just simply does a console.WriteLine of a field in the DaftFrog object.
Both classes are just simple stand in's for the real things once I get around to making the RX code work.
Anyway, back to the problem, so the code above works fine, and if I do a few
_subject.OnNext(new DaftFrog());
calls, the fake dal class, prints out what I expect and everything works fine...
HOWEVER>....
If I then transport this code as is, to a class library, and then new up that class library from within my "static program" as follows:
using System.Reactive.Subjects;
using FakeDal;
using FakeDal.Entites;
namespace RxProducer
{
public class Producer
{
private readonly Subject<DaftFrog> _subject = new Subject<DaftFrog>();
private readonly Repository<DaftFrog> _frogRepo = new Repository<DaftFrog>();
private int _clock;
public void Start()
{
_subject.Subscribe(RespondToNewData);
}
public void Stop()
{
}
public void Tick()
{
if(_clock % 5 == 0)
{
DaftFrog data = new DaftFrog();
_subject.OnNext(data);
}
_clock++;
}
private void RespondToNewData(DaftFrog frog)
{
_frogRepo.Save(frog);
}
}
}
And then use that class in my program
using System;
using RxProducer;
namespace Runner
{
class Program
{
private static readonly Producer _myProducer = new Producer();
static void Main()
{
_myProducer.Start();
while(!line.Contains("quit"))
{
_myProducer.Tick();
line = Console.ReadLine();
}
_myProducer.Stop();
}
}
}
Then my project fails to compile.
Specifically it fails on the line:
_subject.Subscribe(RespondToNewData);
in the RxProducer class library, mores the point, the error the compiler throws back makes little sense either:
Error 1 The best overloaded method match for 'System.Reactive.Subjects.Subject<FakeDal.Entites.DaftFrog>.Subscribe(System.IObserver<FakeDal.Entites.DaftFrog>)' has some invalid arguments H:\programming\rxtesting\RxProducer\Producer.cs 17 7 RxProducer
Error 2 Argument 1: cannot convert from 'method group' to 'System.IObserver<FakeDal.Entites.DaftFrog>' H:\programming\rxtesting\RxProducer\Producer.cs 17 26 RxProducer
At first I thought that it might have been the static thing, so I made everything in the class library static, and that made no difference at all.
Iv'e really not done much with Rx until now, but I work with C# and VS 99% of the time, so I'm aware that the error is telling me it can't convert a type of some description, I just don't understand why it's telling me that, esp when the code works perfectly in the static program, but not in a class library.
Shawty
UPDATE
Second thoughts, I just know there are going to be those who insist that I post the fakedal and daft frog definitions, even though IMHO they won't be required, but to pacify the hordes of pretenders who will ask here they are :-)
using System;
namespace FakeDal
{
public class Repository<T>
{
public void Save(T entity)
{
Console.WriteLine("Here we write T to the database....");
}
}
}
namespace FakeDal.Entites
{
public class DaftFrog
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsTotalyDaft { get; set; }
}
}
Include using System; into file where you have Producer, this will help to convert RespondToNewData to IObserver<T>.
Sounds like the compiler is having trouble inferring the Action...might be missing a using statement for the relevant extension method. Alternatively, try either of:
_subject.Subscribe ((Action<DaftFrog>) RespondToData);
Or:
var obs = Observer.Create ( I forget the overload );
_subject.Subscribe( obs);
Below, I have code for an object that I would like to test. It is in an assembly called Business and I have added the attributes in the AssemblyInfo.cs to make internals visible to the test and rhino mocks which are located in another assembly. When testing the GenerateReport method, I can not fake out the call to ValidateWorkingDirectory when it is "internal" (System.ApplicationException : Must set Working Directory before any method calls.). If I make ValidateWorkingDirectory public, the problem goes away. I thought InternalsVisibleTo would address this issue.
public class MyClass : IMyClass
{
private readonly IMyClassDataProvider _myClassDataProvider;
public virtual string WorkingDirectory { get; set; }
public MyClass(IMyClassDataProvider myClassDataProvider)
{
_myClassDataProvider = myClassDataProvider;
}
internal virtual void ValidateWorkingDirectory()
{
if (string.IsNullOrEmpty(WorkingDirectory))
{
throw new ApplicationException("Must set Working Directory before any method calls.");
}
}
public virtual void GenerateReport(vars)
{
ValidateWorkingDirectory();
InsertData(_myClassDataProvider.GetData(vars), "ReportName");
}
internal virtual void InsertData(DataSet analysis, string fileName)
{
DoSomeStuff();
}
private static void DoSomeStuff()
{
//Whatevs
}
}
//In AssmeblyInfo.cs
[assembly: InternalsVisibleTo("UnitTests.Business")]
[assembly: InternalsVisibleTo("Rhino.Mocks")]
[TestFixture]
public class MyClassTests : TestFixtureBase
{
private MockRepository _mocks;
private IMyClassDataProvider _myClassDataProvider;
private MyClass _myClass;
private var _vars;
[SetUp]
protected void Init()
{
_mocks = new MockRepository();
_myClassDataProvider = _mocks.StrictMock<IMyClassDataProvider >();
_myClass = _mocks.PartialMock<MyClass>(_myClassDataProvider);
_vars = "who cares";
}
[Test]
[ExpectedException(typeof(ApplicationException), ExpectedMessage = "Must set Working Directory before any method calls.")]
public virtual void ShouldThrowAnExceptionIfWorkingDirectoryNotSet()
{
Expect.Call(_myClass.WorkingDirectory).Return(Random.Get<bool>() ? null : string.Empty);
_mocks.ReplayAll();
_myClass.ValidateWorkingDirectory();
_mocks.VerifyAll();
}
[Test]
public virtual void ShouldGenerateReport()
{
DataSet dataSetToReturn = new DataSet();
using (_mocks.Ordered())
{
Expect.Call(() => _myClass.ValidateWorkingDirectory());
Expect.Call(_myClassDataProvider.GetData(vars)).Return(dataSetToReturn);
_myClass.InsertData(dataSetToReturn, "ReportName");
}
_mocks.ReplayAll();
_myClass.GenerateReport(vars);
_mocks.VerifyAll();
}
}
You need to expose your internal members to proxy assembly, not Rhino's assembly itself:
[assembly: InternalsVisibleTo ("DynamicProxyGenAssembly2")]
When a class is mocked, a new class is generated at run-time which is derived from the mocked class. This generated class resides in a separate "temporary" assembly which is called "DynamicProxyGenAssembly2". So, the InternalsVisibleTo attribute needs to be set on the target assembly to allow access to its internal members from the temporary assembly.
This happens to be common misunderstanding, for detailed information on how to use internals visible with Rhino, check this documentation page.
I am attempting to set up a template to create a unit test class with some basic structure and default using statements. I have created a VS2010 custom template to do this and almost everything works correctly.
The issue I have encountered is that I am attempting to reference my project's base namespace in my using statements, and am unable to determine whether there is a parameter that will let me do this.
An example of what I want, assuming my project is called MyProduct.Test:
using NUnit.Framework;
using MyProduct.Test.Base;
namespace MyProduct.Test.BLL.Services.MyService
{
[TestFixture]
public class MyServiceTest : TestBase
{
[SetUp]
public void Setup()
etc...
I can generate everything except for using MyProduct.Test.Base with the template below:
using NUnit.Framework;
using $safeprojectname$.Base;
namespace $rootnamespace$
{
[TestFixture]
public class $safeitemname$ : TestBase
{
[SetUp]
public void Setup()
etc...
Unfortunately, $safeprojectname$ is only available for Project templates, not Item templates.
This template results in the following output:
using NUnit.Framework;
using $safeprojectname$.Base;
namespace MyProduct.Test.BLL.Services.MyService
{
[TestFixture]
public class MyServiceTest : TestBase
{
[SetUp]
public void Setup()
etc...
Is there any way for me to get the actual root namespace of my project (since $rootnamespace$ actually outputs the namespace for the file being added based on its location)?
Note: Obviously I can set this up to work fine for one project, but it would be much more useful to have a template that works for all projects.
Howdy, I have what should be a simple question. I have a set of validations that use System.CompontentModel.DataAnnotations . I have some validations that are specific to certain view models, so I'm comfortable with having the validation code in the same file as my models (as in the default AccountModels.cs file that ships with MVC2). But I have some common validations that apply to several models as well (valid email address format for example). When I cut/paste that validation to the second model that needs it, of course I get a duplicate definition error because they're in the same namespace (projectName.Models). So I thought of removing the common validations to a separate class within the namespace, expecting that all of my view models would be able to access the validations from there. Unexpectedly, the validations are no longer accessible. I've verified that they are still in the same namespace, and they are all public. I wouldn't expect that I would have to have any specific reference to them (tried adding using statement for the same namespace, but that didn't resolve it, and via the add references dialog, a project can't reference itself (makes sense).
So any idea why public validations that have simply been moved to another file in the same namespace aren't visible to my models?
CommonValidations.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;
namespace ProjectName.Models
{
public class CommonValidations
{
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
public sealed class EmailFormatValidAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
if (value != null)
{
var expression = #"^[a-zA-Z][\w\.-]*[a-zA-Z0-9]#[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$";
return Regex.IsMatch(value.ToString(), expression);
}
else
{
return false;
}
}
}
}
}
And here's the code that I want to use the validation from:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using Growums.Models;
namespace ProjectName.Models
{
public class PrivacyModel
{
[Required(ErrorMessage="Required")]
[EmailFormatValid(ErrorMessage="Invalid Email")]
public string Email { get; set; }
}
}
You have declared EmailFormatValidAttribute as a subclass to CommonValidations. As such you need to reference it like CommonValidations.EmailFormatValidAttribute. Or alternatively move the EmailFormatValidAttribute class out of the CommonValidations class.
This should work:
[CommonValidations.EmailFormatValid(ErrorMessage="Invalid Email")]
public string Email { get; set; }
By the way, you can simplify your class as follows:
public class EmailFormatValidAttribute : RegularExpressionAttribute
{
public EmailFormatValidAttribute() :
base(#"^[a-zA-Z][\w\.-]*[a-zA-Z0-9]#[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$")
{}
}
Also, take a look at this: Data Annotations Extensions. It's a great DataAnnotations library which has already the most common validations included in it.