Testing Factory Pattern - c#

I have the small sample factory pattern implementation below, and was wondering if someone can help me write proper Moq unit test cases, for maximum code coverage:
public class TestClass
{
private readonly IService service;
public TestClass(Iservice service)
{
this.service = service;
}
public void Method(string test)
{
service = TestMethod(test);
service.somemethod();
}
private IService TestMethod(string test)
{
if(test == 'A')
service = new A();
if(test == 'B')
service = new B();
return service;
}
}
I am looking for some help in Testing the TestClass and more importantly TestMethod when i send Mock, for example my test method goes below :
[TestMethod]
public void TestCaseA()
{
Mock<IService> serviceMock = new Mock<Iservice>(MockBehaviour.strict);
TestClass tClass = new TestClass(serviceMock.Object);
// The Question is, what is best approach to test this scenario ?
// If i go with below approach, new A() will override serviceMock
// which i am passing through constructor.
var target = tClass.Method("A");
}

You would not mock the TestClass, because that is what you are testing.
For this to work, you need to make a read-only property for service.
public IService Service { get; private set; }
You need to test the way that both the constructor and Method modify the state(in this case Service) of the TestClass instance.
Your test would look something like the following for testing the Method for the B test case:
[TestMethod]
public void TestSomeMethod()
{
// Arrange/Act
var target = new TestClass((new Mock<IService>()).Object);
target.Method("B");
// Assert
Assert.IsInstanceOfType(target.Service, typeof(B));
}
Your test would look something like the following for testing the constructor for the A test case:
[TestMethod()]
public void TestCasesA()
{
// Arrange/Act
var target = new TestClass("A");
// Assert
Assert.IsInstanceOfType(target.service, typeof(A));
}
I would recommend only using the constructor approach to inject your IService. This allows you to have an immutable object that will reduce the state of your application.

Related

How to cast Moq object to check type for dependency injection

I have created a wrapper class for the Microsoft DependencyInjection to simplify some of the calls in my application. I am trying to write unit tests that use Moq to insert objects into the dependency injection service.
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Xunit;
public static class DiService
{
private static IServiceProvider diProvider;
private static Dictionary<Type, object> mockCollection = new Dictionary<Type, object>();
public static IServiceCollection ServiceCollection { get; } = new ServiceCollection();
public static bool UseTestMode { get; set; } = false;
public static T GetRequiredService<T>()
where T : class
{
if( UseTestMode )
{
if( mockCollection.ContainsKey(typeof(T)) )
{
return mockCollection[typeof(T)] as T;
}
}
if( diProvider == null )
{
diProvider = ServiceCollection.BuildServiceProvider();
}
return diProvider.GetRequiredService<T>();
}
public static void RegisterMock(Type interfaceType, object mockObjectInstance)
{
if( !mockObjectInstance.GetType().IsInstanceOfType(interfaceType) )
{
throw new InvalidCastException($"mockObjectInstance must be of type {interfaceType}");
}
if( mockCollection.ContainsKey(interfaceType) )
{
mockCollection[interfaceType] = mockObjectInstance;
}
else
{
mockCollection.Add(interfaceType, mockObjectInstance);
}
}
}
Testing related code
public interface ITestInterface
{
}
public class TestClass : ITestInterface
{
}
[Fact]
public void GetRequiredService_MoqObject_NormalOperation()
{
Mock<ITestInterface> mock = new Mock<ITestInterface>();
DiService.UseTestMode = true;
DiService.RegisterMock(typeof(ITestInterface), mock.Object);
ITestInterface testResult = DiService.GetRequiredService<ITestInterface>();
Assert.NotNull(testResult);
}
This works great for mocks that I great myself, but not when I try to use Moq. The InvalidCastException is thrown for Moq objects.
In the RegisterMock method, I haven't been able to figure out how to cast the Moq object to check if it implements the proper interface. The Moq object actually doesn't inherit from the interface it's mocking (the interface is ITestInterfaceProxy). I also can't figure out how to cast an object to a type specified by a variable.
Is there any way to actually perform the error check in RegisterMock?
Thanks ahead of time for your responses.
Addendum:
Based on Peter Csala's comment, I am adding this example of how I'm using the DiService above. I hope I haven't simplified it to the point of uselessness.
[Fact]
public void TestLoad()
{
DiService.UseTestMode = true;
Mock<IDataAccess> mockDataAccess = new Mock<IDataAccess>();
DiService.RegisterMock(typeof(IDataAccess), mockDataAccess.Object);
Data testData = GenFu.A.New<Data>();
mockDataAccess.Setup(mock => mock.LoadData(It.IsAny<string>()).Returns(testData);
// Assuming that inside MyViewModel.LoadData there is some process that generates an IDataAccess and calls IDataAccess.LoadData
MyViewModel viewModel = new MyViewModel();
Data loadedData = viewModel.LoadData("some id");
Assert.Equal(testData, loadedData);
}
Just to clarify certain things:
I am trying to write unit tests that use Moq to insert objects into the dependency injection service
In case of unit testing the DI is not in use. Rather you explicitly pass the mocked object to your system under test. For example:
Your System under test class
private readonly IDependency dependency;
public SampleUsage(IDependency dep)
=> dependency = dep;
Your test code
//Arrange
Mock<IDependency> mockedDep = new Mock<IDependency>();
mockedDep.Setup(...).Returns(...);
var sut = SampleUsage(mockedDep.Object);
//Act
var actualResult = sut.XYZMethod();
In case of integration or end-to-end testing you rely on the DI system, but not by replacing some components with a mocked one. Rather you are using different configuration options.
For example if you have a component that communicates with a 1st or 3rd party REST service then you should change the base address configuration of that service. That new address should point to a locally running http mock server. You can create one with a library like WireMock.NET.

How to write a unit test without interface implementation

I'm new to unit testing.
I have to test RefreshAmount in the following code:
private readonly int id;
private readonly IService service;
public MyClass(int id, IService service)
{
this.id= id;
this.service= service;
}
public double Number { get; private set; }
public void RefreshAmount()
{
Number= service.GetTotalSum(id);
}
What would be a correct unit test to write for RefreshAmount?
You need to mock IService. There are various frameworks that help automate this for you (like Moq) but here's a simple example:
public class MockService : IService
{
public double GetTotalSum(int id)
{
return 10;
}
}
Basically, a mock implements your interface but just returns hard-coded (or otherwise well-known) data. That makes it easy to know what your expected value should be! Now you can use that to do your test:
public void TestMethod()
{
MyClass testObj = new MyClass(1, new MockService());
testObj.RefreshAmount();
Assert.Equals(10, testObj.Number);
}
Start simple attempting the "Sunny Day" or "Happy Path" first...
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var service = new MyService();
int SomeProperInteger = GetNextInteger();
double SomeProperAmount = .50;
var actual = service.GetTotalSum(SomeProperInteger);
double expected = SomeProperInteger * SomeProperAmount;
Assert.IsTrue(expected = actual, "Test Failed, Expected amount was incorrect.");
}
private int GetNextInteger()
{
throw new System.NotImplementedException();
}
}
Start with testing a service object that will be used in production as shown above. You will have to look at the code to see what GetTotalSum is supposed to do or look at the specifications. Once the "Happy path" works then you will alter at most 1 parameter at a time using Boundaries. The Boundaries would in code above come from GetNextInteger or a list of proper values. You must write code to anticipate the expected value to compare.
After the service is validated to be working as designed, move on to the class that uses the service using the same techniques.

Is there a way to avoid passing null parameters to class under test when the dependency are not used?

Given the following class and test
public class UserService
{
private IUserRepository _userRepo;
public UserService(IUserRepository userRepo)
{
_userRepo = userRepo;
}
public User Get(int id)
{
var user = _userRepo.Get(id);
if(user == null)
throw new CustomException();
return user;
}
}
Unit Tests:
[Fact]
public void MissingUser_ThrowsException()
{
// Arrange
var userService = new UserService(null);
// Act
Action result = userService.Get(0);
// Assert
result.Throws<CustomException>();
}
[Fact]
public void ExistingUser_ReturnsUser()
{
// Arrange
var user = new User()
{
Id = 0
};
var userRepo = new Mock<IUserRepository>();
userRepo
.Setup(m => m.Get(0))
.Return(user);
var userService = new UserService(userRepo.Object);
// Act
var result = userService.Get(0);
// Assert
Assert.Equal(user, result);
}
Is there a way to avoid passing in null parameters into the constructor when I know the dependencies will not be called in the test? If the class under test now requires a new constructor argument, I'd need to add another null parameter to this test and all other test that don't utilize that dependency.
Update:
I'm using Moq and XUnit. That is, I want to avoid using setup methods as I agree with the philosophy of XUnit. However, any mocking framework would still have the same problem.
I added another test that uses the mock. The case that I'm trying to avoid is having to deal with adding additional parameters to the constructor of the class under test when I don't need to.
If I were to add another dependency in the constructor of UserService that is used by the Get method, I would want only the second test to fail at run time. Currently, I would need to add another parameter to the ctor of UserService for both tests.
The more I think about this, the more I realize I want to use a IoC to construct my concrete (class under test). Is using an DI/IoC container in unit tests recommended?
Although it is odd that you aren't using a mocking framework, it sounds like your question relates to another issue. Many unit test will be written and the constructor for the class under test may change. What you are asking, I think, is how do you avoid the busy work of changing each and every test when you make changes to the constructor signature of the class under test?
One way to avoid this is to use a helper class to manage the construction of your test instances. Here's a simple example:
public class UserServcieMockManager
{
//mock objects here if you're using a mocking framework
public UserService GetServiceForTesting()
{
return new UserService(null); //here's where the mocks would be used
}
}
The reason I've called this class "Mock Manager" is because this is also where you would instantiate your mocks. Then when the constructor signature changes, you only have to change the one method that creates the test instance.
This type of helper class also becomes very useful as a way to centralize the setup logic for mocking scenarios that are reused between tests.
The more I think about this, the more I realize I want to use a IoC to construct my concrete (class under test). Is using an DI/IoC container in unit tests recommended?.
I prefer creation of class under test within Setup or Init method and see no reason to avoid doing it.
If you want to use IoC/DI to create your class under test, you can use AutoMoq (see on GitHub, NuGet package).
There is an exmple of usage:
[TestClass]
public class ServiceConsumerTestWithAutoMoq
{
[TestMethod]
public void DoA()
{
//arrange
var mocker = new AutoMoqer();
var sut = mocker.Create<ServiceConsumer>();
//act
sut.DoA();
//assert
mocker.GetMock<IServiceA>().Verify(it => it.Do(), Times.Once());
mocker.GetMock<IServiceB>().Verify(it => it.Do(), Times.Never());
}
[TestMethod]
public void DoB()
{
//arrange
var mocker = new AutoMoqer();
var sut = mocker.Create<ServiceConsumer>();
//act
sut.DoB();
//assert
mocker.GetMock<IServiceA>().Verify(it => it.Do(), Times.Never());
mocker.GetMock<IServiceB>().Verify(it => it.Do(), Times.Once());
}
}
public interface IServiceConsumer
{
void DoA();
void DoB();
}
public class ServiceConsumer : IServiceConsumer
{
public IServiceA serviceA { get; set; }
public IServiceB serviceB { get; set; }
public ServiceConsumer(
IServiceA serviceA,
IServiceB serviceB)
{
this.serviceA = serviceA;
this.serviceB = serviceB;
}
public void DoA()
{
serviceA.Do();
}
public void DoB()
{
serviceB.Do();
}
}
public interface IServiceA
{
void Do();
}
public interface IServiceB
{
void Do();
}
There is another library Moq.AutoMocker that is developed by member of Moq Team, Tim Kellogg.
But I'd rather use Setup or Init method to create class under test.
There is code example that I would use to solve your issue.
[TestClass]
public class ServiceConsumerTestWithInit
{
private Mock<IServiceA> serviceAMock;
private Mock<IServiceB> serviceBMock;
private IServiceConsumer sut;
[TestInitialize]
public void Initialize()
{
serviceAMock = new Mock<IServiceA>();
serviceBMock = new Mock<IServiceB>();
sut = new ServiceConsumer(
serviceAMock.Object,
serviceBMock.Object);
}
[TestMethod]
public void DoA()
{
//act
sut.DoA();
//assert
serviceAMock.Verify(it => it.Do(), Times.Once());
serviceBMock.Verify(it => it.Do(), Times.Never());
}
[TestMethod]
public void DoB()
{
//act
sut.DoB();
//assert
serviceAMock.Verify(it => it.Do(), Times.Never());
serviceBMock.Verify(it => it.Do(), Times.Once());
}
}
Instead of passing null, I'd mock IUserRepository and simply pass the mocked object.
This way a check against null doesn't throw e.g. an ArgumentException... (if you would implement such checks which is pretty handy in DI code).
If you still do not want that, implement another empty ctor for testing. Mark it internal and make the assembly internals visible to your test project. Or protected and have a derived test class.
No there is no way you can force the caller to always pass a not null value.
The best you can do is use factory pattern to pass IRepositoryFactory to the constructor so you will only have 1 parameter and will need to check for null for only that parameter.
Your RepositoryFactory will return the types for each repository you will need.
How to implement a generic RepositoryFactory?
It sound like you are looking for a Mock framework.
Personally, I Prefer Rhino Mocks
I am not sure I remember the syntax for it, but it is very easy. If I am not mistaking it is something like:
var mockedUserReop = MockRepository.GenerateMock<IUserRepository >();
The full method will be:
[TestInitialize, SetUp]
public void TestInitilize()
{
var mockedUserReop = MockRepository.GenerateMock<IUserRepository >();
UserService = new UserService(mockedUserReop );
}

Moq a MEF Import?

I have a class A which has the following:
public class A {
[Import(typeof(IMyService)]
public IMyService MyService { get; set; }
public A() {
CompositionInitializer.SatisfyImports(this);
}
public void DoWork() {
//Blah
MyService.DoIt();
//Blah
}
}
And a Test to test this (seperate Dll - obviously)
[TestMethod]
public void TestDoWork() {
//Blah
DoWork();
//Assert assert
}
This fails as attempting to call 'MyService' gives me null.
I've then tried:
[ClassInitialize]
public void InitialiseClass() {
var myService = new Mock<IMyService>();
MyService = myService.Object;
}
with 'MyService' declared as:
[Export(typeof(IMyService))]
public IMyService MyService { get; set; }
But still no joy, am I missing something - is this even possible?
I'm using SL3, MEF Preview 9 and MOQ.
Any help appreciated!
Cheers
Chris
Your class should look like this:
public class A
{
private readonly IMyService _myService;
[ImportingConstructor]
public A(IMyService myService)
{
_myService = myService;
}
public void DoWork() {
//Blah
_myService.DoIt();
//Blah
}
}
And your test should look like this:
[TestMethod]
public void DoWork_invokes_IMyService_DoIt()
{
// arrange mock and system under test
var myService = new Mock<IMyService>();
var a = new A(myService.Object);
// act
a.DoWork();
// assert that DoIt() was invoked
myService.Verify(x => x.DoIt());
}
The fact that you use MEF should not be important in unit tests. MEF only comes into play when wiring many components together, which is exactly the opposite of what happens in a unit test. A unit test is by definition a test of a component in isolation.
Edit: if you prefer property injection, then your class doesn't need a constructor and the arrange part in your unit test should look like this instead:
var myService = new Mock<IMyService>();
var a = new A();
a.MyService = myService.Object;
Where you've added [Export] to your IMyService instance, have you actually added that to the composition container? If not, it won't take part in composition. To add a mocked object to the container, do the following:
container.ComposeExportedValue<IMyService>(mock.Object);
Or just:
container.ComposeExportedValue(mock.Object); // type inference.
Doing this before you've created an instance of A will enable it to be composed inside your A instance.
You shouldn't be firing up MEF in your unit tests. Composition is way beyond unit test's scope, not dissimilar to an IoC container.
Insted, you should inject required dependencies manually:
[TestClass]
public class ATest {
Mock<IMyService> myService ;
[TestInitialize]
public void InitialiseClass() {
myService = new Mock<IMyService>();
}
[TestMethod]
public void DoWorkShouldCallDoIt {
A a = new A();
a.MyService = myService.Object;
a.DoWork();
myService.Verify(m=>m.DoIt(), Times.Once());
}
}

Rhino Mocks, void and properties

Just starting out with Rhino Mocks and im having a very simple problem, how do I mock a class with a void which sets a property?
class SomeClass : ISomeClass
{
private bool _someArg;
public bool SomeProp { get; set; }
public SomeClass(bool someArg)
{
_someArg = someArg;
}
public void SomeMethod()
{
//do some file,wcf, db operation here with _someArg
SomeProp = true/false;
}
}
Obviously this is a very contrived example, Thanks.
In your example you won't need RhinoMocks because you're apparently testing the functionality of the class under test. Simple unit testing will do instead:
[Test]
public void SomeTest()
{
var sc = new SomeClass();
// Instantiate SomeClass as sc object
sc.SomeMethod();
// Call SomeMethod in the sc object.
Assert.That(sc.SomeProp, Is.True );
// Assert that the property is true...
// or change to Is.False if that's what you're after...
}
It's much more interesting to test mocks when you have a class that has dependencies on other classes. In your example you mention:
//do some file, wcf, db operation here with _someArg
I.e. you expect some other class to set SomeClass's property, which makes more sense to mocktest. Example:
public class MyClass {
ISomeClass _sc;
public MyClass(ISomeClass sc) {
_sc = sc;
}
public MyMethod() {
sc.SomeProp = true;
}
}
The required test would go something like this:
[Test]
public void MyMethod_ShouldSetSomeClassPropToTrue()
{
MockRepository mocks = new MockRepository();
ISomeClass someClass = mocks.StrictMock<ISomeClass>();
MyClass classUnderTest = new MyClass(someClass);
someClass.SomeProp = true;
LastCall.IgnoreArguments();
// Expect the property be set with true.
mocks.ReplayAll();
classUndertest.MyMethod();
// Run the method under test.
mocks.VerifyAll();
}
Depends on how much fidelity you'd like in your mock object. The easy way to do it is to not worry about it and write out some dumb expect statements.
[Test]
public void SomeTest()
{
MockRepository mocks = new MockRepository();
ISomeClass mockSomeClass = mocks.StrictMock<ISomeClass>();
using(mocks.Record())
{
using(mocks.Ordered())
{
Expect.Call(MockSomeClass.SomeProp).Return(false);
Expect.Call(delegate{MockSomeClass.SomeMethod();});
Expect.Call(MockSomeClass.SomeProp).Return(true);
}
}
}
If you want something that acts more like the real object without a canned set of ordered responses you'll have to set up delegates with the do method on the expect.
delegate bool propDelegate();
delegate void methodDelegate();
private bool m_MockPropValue = false;
[Test]
public void SomeTest()
{
MockRepository mocks = new MockRepository();
ISomeClass mockSomeClass = mocks.StrictMock<ISomeClass>();
using(mocks.Record())
{
SetupResult.For(MockSomeClass.SomeProp).Do(new propDelegate(delegate
{
return this.m_MockPropValue;
}));
Expect.Call(delegate{MockSomeClass.SomeMethod();}).Do(new methodDelegate(delegate
{
this.m_MockPropValue = true;
}));
}
}
When your preparing something with either SetupResult.For or Expect.Call you need to ensure that they are virtual, otherwise RhinoMocks will be unable to make its own implementation.
Otherwise it's just a matter of setting the results and doing expected calls as Scott Pedersen has shown
It's not totally clear from the question what the object you're trying to test is - if you simply want to check that SomeClass.SomeMethod() sets a property then you don't need mocking since you can just do a simple state-based test:
[TestMethod]
public void SomeMethodTest()
{
SomeClass s = new SomeClass();
s.SomeMethod();
Assert.AreEqual(expectedValue, s.SomeProp);
}
Alternatively, if SomeClass is a dependency for some other class, and you want to test the interaction between that class and SomeClass, then you set up the expectation on the method call during the 'Record' section of the test using RhinoMock, like this:
[TestMethod]
public void CheckInteractionWithSomeClass()
{
MockRepository mocks = new MockRepository();
ISomeClass someClass = mocks.StrictMock<ISomeClass>();
using (mocks.Record())
{
//record expection that someClass.SomeMethod will be called...
someClass.SomeMethod();
}
using (mocks.Playback())
{
//setup class under test - ISomeClass is injected through the constructor here...
ClassUnderTest o = new ClassUnderTest(someClass);
o.MethodOnClassUnderTestThatShouldCallSomeClass.SomeMethod();
//any other assertions...
}
}

Categories

Resources