I have coded a constructor for a class and I am testing for each parameter being null. See example below:
public MyClass(IObjectA objA, IObjectB objB) : IMyClass
{
if (objA == null)
{
throw new ArgumentNullException("objA");
}
if (objB == null)
{
throw new ArgumentNullException("objB");
}
...
}
Usually I unit test (using Moq) this by mocking out IObjectA and IObjectB and passing them in. The example above would create 2 unit tests to test each scenario.
The problem I have is when a 3rd parameter is passed into the constructor. It requires that I alter my previous tests, as I suddenly get a "No constructor for MyClass has 2 parameters" type exception.
I also use AutoMockContainer. Essentially I'd like to be able to test the constructor by registering a null object in the container. For example:
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void ConstructionThrowsExceptionForNullObjA()
{
// Arrange.
var container = new AutoMockContainer(new MockRepository(MockBehavior.Default));
container.Register<IObjectA>(null);
// Act.
var sut = container.Create<MyClass>();
}
Then it doesn't matter how many new parameters are added to the constructor. I will not have to update my unit tests.
Sadly, the above unit test passes. But for the wrong reason. The Register<T>() method throws the ArgumentNullException not the code executed in the 'Act' section.
Does anyone have a suggestion for being able to test constructor parameters and not have to revisit the unit test when new parameters are later added?
You can help alleviate some of this burden by utilizing either the factory or builder patterns to create your objects.
A simplified example of the builder pattern would be:
public class Foo
{
public string Prop1 { get; private set; }
public Foo(string prop1)
{
this.Prop1 = prop1;
}
}
[TestClass]
public class FooTests
{
[TestMethod]
public void SomeTestThatRequiresAFoo()
{
Foo f = new Foo("a");
// testy stuff
}
[TestMethod]
public void SomeTestThatRequiresAFooUtilizingBuilderPattern()
{
Foo f = new FooBuilder().Build();
}
[TestMethod]
public void SomeTestThatRequiresAFooUtilizingBuilderPatternOverrideDefaultValue()
{
Foo f = new FooBuilder()
.WithProp1("different than default")
.Build();
}
}
internal class FooBuilder
{
public string Prop1 { get; private set; }
// default constructor, provide default values to Foo object
public FooBuilder()
{
this.Prop1 = "test";
}
// Sets the "Prop1" value and returns this, done this way to create a "Fluent API"
public FooBuilder WithProp1(string prop1)
{
this.Prop1 = prop1;
return this;
}
// Builds the Foo object by utilizing the properties created as BuilderConstruction and/or the "With[PropName]" methods.
public Foo Build()
{
return new Foo(
this.Prop1
);
}
}
This way if/when your Foo object changes, it's a bit easier to update your unit tests to take the changes into account.
Consider:
public class Foo
{
public string Prop1 { get; private set; }
public string Prop2 { get; private set; }
public Foo(string prop1, string prop2)
{
this.Prop1 = prop1;
this.Prop2 = prop2
}
}
With this implementation your unit tests will break, but updating your builder is much easier than updating each unit test relying on the proper construction of a Foo
internal class FooBuilder
{
public string Prop1 { get; private set; }
public string Prop2 { get; private set; }
// default constructor, provide default values to Foo object
public FooBuilder()
{
this.Prop1 = "test";
this.Prop2 = "another value";
}
// Sets the "Prop1" value and returns this, done this way to create a "Fluent API"
public FooBuilder WithProp1(string prop1)
{
this.Prop1 = prop1;
return this;
}
// Similar to the "WithProp1"
public FooBuilder WithProp2(string prop2)
{
this.Prop2 = prop2;
return this;
}
// Builds the Foo object by utilizing the properties created as BuilderConstruction and/or the "With[PropName]" methods.
public Foo Build()
{
return new Foo(
this.Prop1,
this.Prop2
);
}
}
With this new implementation of Foo and FooBuilder, the only unit test that would break is the one that created the Foo manually, the FooBuilder utilizing unit tests will still work without error.
This is a simplified example, but imagine if you had 20-30 unit tests reliant on the construction of a Foo object. Rather than updating those 20-30 unit tests, you can simply just update your builder to properly construct the Foo object.
In your example to unit test a null in the constructor, you could write the unit test using the builder pattern as such:
[TestMethod]
public void TestWithNullInFirstParam()
{
Foo f = new FooBuilder()
.WithProp1(null)
.Build()
// in this case "f" will have Prop1 = null, prop2 = "another value"
}
Related
I have a class that I'm trying to get under unit tests. The class exposes a struct as a public property. The struct also has some public methods (that do much more than a method in a struct should). I can't make changes to the struct (I don't own that code and it would be too risky at the moment).
Mock doesn't work on value types. Is there a way to effectively "mock a struct"?
public class SystemUnderTest
{
public FragileStructCantChange myStruct {get; set;}
public string MethodUnderTest()
{
if(myStruct.LongRunningMethod() == "successful")
return "Ok";
else
return "Fail";
}
}
public struct FragileStructCantChange
{
public string LongRunningMethod()
{
var resultString = DoStuff(); //calls other subsystems
return resultString;
}
}
Referencing a struct through an interface effectively turns it into a reference type, through a process called "boxing". Boxing a struct can cause some subtle changes in behavior, which you should read about before making your decision.
Another option is to add some indirection between the struct and the code under test. One way is to add a to specify a test value.
public class SystemUnderTest
{
public FragileStructCantChange myStruct { get; set; }
// This value can be overridden for testing purposes
public string LongRunningMethodOverride { get; set; }
public string MethodUnderTest()
{
// Call the indirect Func instead of referencing the struct directly
if (LongRunningMethod() == "successful")
return "Ok";
else
return "Fail";
}
private string LongRunningMethod()
=> LongRunningMethodOverride ?? myStruct.LongRunningMethod();
}
public class Tests
{
[Fact]
public void TestingSideDoor()
{
var sut = new SystemUnderTest();
// Override the func to supply any test data you want
sut.LongRunningMethodOverride = "successful";
Assert.Equal("Ok", sut.MethodUnderTest());
}
}
Another way is to expose an overridable function pointer...
public class SystemUnderTest
{
public FragileStructCantChange myStruct { get; set; }
// This Func can be overridden for testing purposes
public Func<string> LongRunningMethod;
public SystemUnderTest() {
LongRunningMethod = () => myStruct.LongRunningMethod();
}
public string MethodUnderTest()
{
// Call the indirect Func instead of referencing the struct directly
if (LongRunningMethod() == "successful")
return "Ok";
else
return "Fail";
}
}
public class Tests
{
[Fact]
public void TestingSideDoor()
{
var sut = new SystemUnderTest();
// Override the func to supply any test data you want
sut.LongRunningMethod = () => "successful";
Assert.Equal("Ok", sut.MethodUnderTest());
}
}
Another option is to use a virtual method, which can be faked either by a subclass or a mocking framework (Moq, in this example)...
public class SystemUnderTest
{
public FragileStructCantChange myStruct { get; set; }
// This method can be overridden for testing purposes
public virtual string LongRunningMethod()
=> myStruct.LongRunningMethod();
public string MethodUnderTest()
{
// Call the indirect method instead of referencing the struct directly
if (LongRunningMethod() == "successful")
return "Ok";
else
return "Fail";
}
}
public class Tests
{
[Fact]
public void TestingSideDoor()
{
var sut = new Mock<SystemUnderTest>();
// Override the method to supply any test data you want
sut.Setup(m => m.LongRunningMethod())
.Returns("successful");
Assert.Equal("Ok", sut.Object.MethodUnderTest());
}
}
I won't claim that either of these options is pretty, and I'd think hard about safety/security before putting this sort of backdoor into a shared library. An interface is usually preferable, when viable.
This sort of thing works, though, and I think it can be a fair compromise when you're faced with test-unfriendly code that you don't want to invasively refactor.
So I'm trying to mock an interface that contains a property that my unit test has to set initially, which is then altered by the subject under test, and then my assertion looks at the result.
The code under test looks like this:
public class Foo
{
IEnumerable<int> IntList { get; set; }
public void Bar(IBaz baz)
{
if (baz == null)
throw new ApplicationException();
if (baz.IntList == null)
baz.IntList = new List<int>();
this.IntList = baz.IntList;
}
}
I'm mocking my interface in a factory like this:
public class BazFactory
{
public IEnumerable<int> IntList { get; set; }
public IBaz Create()
{
IBaz baz = Mock.Create<IBaz>();
baz.Arrange(x => x.IntList).Returns(this.IntList);
return baz;
}
}
And my unit test consumes it all like this:
[Fact]
public void WithNullIntList_InitializesNew()
{
//Arrange
Foo foo = new Foo();
BazFactory factory = new BazFactory();
IBaz baz = factory.Create();
//Act
foo.Bar(baz);
//Assert
Assert.NotNull(foo.IntList);
}
Obviously, this isn't working, because though foo.Bar() tries to change baz.IntList, it still returns factory.IntList, which hasn't changed.
What I need is to be able to arrange baz.IntList so that when it is set, the value passed to it is diverted to factory.IntList instead. I have only seen documentation on how to do this with a variable inside the mock class, and how to do it with a method, but not with a property's setter.
I feel like I should be able to add a line to BazFactory.Create() like this, but the following code doesn't work.
baz.ArrangeSet(x => this.IntList = x.IntList);
How can I express "the value passed to baz.IntList" in the context of an action?
If it makes a difference, I am using the Lite version of JustMock.
I wish to test a method which queries a third-party library. The library returns an object with a IReadOnlyCollection property.
There is no constructor to set the value of the property and the object has no interface for me to mock.
I have used Moq to mock the interface for the service that I call, but I can't create a mocked return value as I can't set the property.
public interface IHitService {
public Hit GetHit();
}
public class Hit {
public Hit() {
}
public IReadOnlyCollection<string> Result { get; }
}
public class TestingClass {
public void MyTest() {
Hit hit = new Hit() {
// cannot set this property
Result = new List<string>() { "hello","goodbye" };
}
Mock<IHitService> service = new Mock<IHitService>();
service.Setup(c => c.GetHit).Returns(hit);
}
}
What would be the best way for me to generate the return value to test my method? Wrapping the object with a new property to hide the base does not work.
You can use unit-test frameworks that allow you to change the behavior of a concrete object, for example in this case i used Typemock Isolator to try and solve your issue, it allows you to change the the return value of the result property so can "set" for your test without changing your code or adding extra code:
public void TestMethod1()
{
List<string> s = new List<string> { "sfas", "asfsa", "blbba" };
var hit = Isolate.Fake.NextInstance<Hit>();
Isolate.WhenCalled(() => hit.Result).WillReturnCollectionValuesOf(s);
}
In this test i mocked the Hit class and modified the return value of the Result property to a list of strings i created.
If you need to test a third-party library, it would be a better idea to create your own abstraction (interface) and rely on that for both testing and real code:
public interface IHitService
{
IHit GetHit();
}
public interface IHit
{
IReadOnlyCollection<string> Result { get; }
}
In your application code, you can create a simple wrapper class that implements IHit by delegating to the concrete third-party class. Now you can test the interface by mocking it as needed.
In general, if you can't change 3rd party code, build an adapter to it and use your own abstraction :-
public interface IHit
{
IReadOnlyCollection<string> Result { get; }
}
public interface IHitService
{
IHit GetHit();
}
public class HitAdapter : IHit
{
private Hit _hit;
public HitAdapter(Hit hit)
{
_hit = hit;
}
public IReadOnlyCollection<string> Result => _hit.Result;
}
public class TestingClass
{
public void MyTest()
{
var hitMock = new Mock<IHit>();
hitMock.Setup(c => c.Result).Returns<IReadOnlyCollection<string>>(x => new List<string>() {"hello", "goodbye"});
var service = new Mock<IHitService>();
service.Setup(c => c.GetHit()).Returns<IHit>(x => hitMock.Object);
}
}
I have these interfaces
public interface Interface1 { Interface2 Items {get;} }
public interface Interface2 { Guid? ApplicationTypeId { get; } }
public interface Interface3 { Class1 Item {get;} }
public interface Interface4 { Guid? ApplicationId { get; set; } }
A class inherits the first interface
public class Class1 : Interface1 {
public Interface2 Items { get; }
}
Another class which consists of few guids
public static class ContentTypeIds
{
public static Guid ContentGuid1 => new Guid("{11798e9d-a167-4cfc-8cfa-9a24fd6caf25}");
public static Guid ContentGuid2 => new Guid("{7d22f5bb-37fd-445a-b322-2fa1b108d260}");
}
I need to unit test the following property
private readonly Interface3 _interface3;
public Ticket Current
{
get
{
//This line is very complicated
Interface4 itemByContentType = _interface3.Item?.Items.GetItemByContentType(ContentTypeIds.ContentGuid2);
if ( itemByContentType?.ContentId != null )
return Get(itemByContentType.ContentId.Value);
return null;
}
}
My test class goes here
[Test]
public class TestClass {
var mock1 = new Mock<Interface1>();
var mock2 = new Mock<Interface2>();
var mock3 = new Mock<Interface3>();
mock1.SetupAllProperties();
mock2.SetupAllProperties();
mock3.SetupAllProperties();
}
The value for 'itemByContentType' goes null.
Could anyone help me to make it simple and testable as it is getting complicated to test this property? I'm using Moq. I will appreciate any help.
Thanks
I'm not an expert on Moq, but it looks like its SetupAllProperties method simply sets up all the properties to act like properties (i.e. the object it creates has a persistent member which can support GET/SET operation). If this isn't done, then as I understand it, the properties will still be available, but they'll always resolve to null. This is very handy when preparing the Mock objects, but on its own, though, that doesn't setup the properties with any sort of value.
I think what you should be doing is using Moq's SetupGet in conjunction with the Returns method to prepare the GET of the Items property with a specific value.
Here is some (simplified) sample code, to demonstrate this:
public interface IFoo { Guid? ApplicationId { get; set; } }
public interface IBar { IFoo Items { get; } }
class Program
{
static void Main(string[] args)
{
// SETUP
// Prepare mocks
Mock<IFoo> MockFoo = new Mock<IFoo>();
Mock<IBar> MockBar = new Mock<IBar>();
// Seting up properties allows us read/write Foo's ApplicationId
MockFoo.SetupAllProperties();
// The mocked Foo object should be what's returned when Items is requested
var expectedFoo = MockFoo.Object;
// Setup the Bar object to return that mocked Foo
MockBar.SetupGet(x => x.Items).Returns(expectedFoo);
// The value written here will be persistent due to SetupAllProperties
expectedFoo.ApplicationId = new Guid("{7d22f5bb-37fd-445a-b322-2fa1b108d260}");
// ACTION
// When the "Items" property is accessed, the IFoo we get should be what we mocked...
var actualFoo = MockBar.Object.Items;
// ... and we can read the value set to Foo's ApplicationId
var actualAppId = actualFoo.ApplicationId;
}
}
I'm starting to use MEF, and I have a class with multiple constructors, like this:
[Export(typeof(ifoo))]
class foo : ifoo {
void foo() { ... }
[ImportingConstructor]
void foo(object par1) { ... }
}
I am using catalog.ComposeExportedValue() when composing to supply the par1
value to second constructor:
...
catalog.ComposeExportedValue(par1Value);
catalog.ComposeParts(this);
...
To hold the components I'm using:
[ImportMany(typeof(ifoo))]
public List<Lazy<ifoo, ifoometadata>> FooList { get; set; }
And to create the foo instance I'm using the value property, FooList[0].Value.
Everthing works fine, except that the second constructor of the foo class is never called. What's wrong?
How do I select the constructor I want to use when MEF instantiates the class?
MEF should use the constructor you put the ImportingConstructorAttribute on. I'm not sure what is happening for you, I wasn't able to reproduce the issue. Here is a test which shows using an ImportingConstructor on a class that also has a default constructor:
[TestClass]
public class MefTest
{
public const string ConstructorParameterContract = "FooConstructorParameterContract";
[TestMethod]
public void TestConstructorInjectionWithMultipleConstructors()
{
string ExpectedConstructorParameterValue = "42";
var catalog = new TypeCatalog(typeof(Foo), typeof(FooImporter));
var container = new CompositionContainer(catalog);
container.ComposeExportedValue<string>(ConstructorParameterContract, ExpectedConstructorParameterValue);
var fooImporter = container.GetExportedValue<FooImporter>();
Assert.AreEqual(1, fooImporter.FooList.Count, "Expect a single IFoo import in the list");
Assert.AreEqual(ExpectedConstructorParameterValue, fooImporter.FooList[0].Value.ConstructorParameter, "Expected foo's ConstructorParameter to have the correct value.");
}
}
public interface IFoo
{
string ConstructorParameter { get; }
}
[Export(typeof(IFoo))]
public class Foo : IFoo
{
public Foo()
{
ConstructorParameter = null;
}
[ImportingConstructor]
public Foo([Import(MefTest.ConstructorParameterContract)]string constructorParameter)
{
this.ConstructorParameter = constructorParameter;
}
public string ConstructorParameter { get; private set; }
}
[Export]
public class FooImporter
{
[ImportMany]
public List<Lazy<IFoo>> FooList { get; set; }
}
Are you passing an instance of the foo class into the ComposeExportedValue method? In that case the object has already been constructed and the constructor can't be called again, so MEF will ignore the constructor imports.