i am working with visual studio and writing Nunit test cases.
While Writing test cases i encountered a class which is having a protected method and that method so throwing an exception of "NotImplementedException" type.
I tried to use Invoke key-word but Ncover is not cover that portion.
I also tried to use try catch but my code reviewer is saying not to use try catch block in test cases.
So, friend is there any other way to write test case for such type of issue.
I am mentioning the class and test cases, please tell me how to solve it.
Class File:-
public class UpdateMacActivityPriorityTranslator : EntityMapperTranslator<object, CSUpdateMACActivityPriorityResponseType>
{
protected override CSUpdateMACActivityPriorityResponseType BusinessToService(IEntityTranslatorService service, object value)
{
throw new NotImplementedException();
}
}
Test case:-
public void BusinessToServiceTest()
{
var updateMacActivityPriorityTranslator = new UpdateMacActivityPriorityTranslator();
var service = MockRepository.GenerateStub<IEntityTranslatorService>();
var value = new object();
var invokeProtectedBusinessToService = new PrivateObject(updateMacActivityPriorityTranslator,new PrivateType( typeof(UpdateMacActivityPriorityTranslator)));
NUnit.Framework.Assert.Throws<NotImplementedException>(
() =>
invokeProtectedBusinessToService.Invoke("BusinessToService",
new object[] { service, value }));
}
If your class (fixture) containing the test method BusinessToServiceTest already derives from (has as base class) UpdateMacActivityPriorityTranslator, I guess you could just do:
public void BusinessToServiceTest()
{
var updateMacActivityPriorityTranslator = new UpdateMacActivityPriorityTranslator();
var service = MockRepository.GenerateStub<IEntityTranslatorService>();
var value = new object();
NUnit.Framework.Assert.Throws<NotImplementedException>(
() => updateMacActivityPriorityTranslator.BusinessToService(service, value)
);
}
or you could just use this instead of updateMacActivityPriorityTranslator, so:
public void BusinessToServiceTest()
{
var service = MockRepository.GenerateStub<IEntityTranslatorService>();
var value = new object();
NUnit.Framework.Assert.Throws<NotImplementedException>(
() => BusinessToService(service, value)
);
}
In your test fixture, implement a private nested class that inherits from UpdateMacActivityPriorityTranslator and exposes the protected method via a public test method:
private class TestUpdateMacActivityPriorityTranslator : UpdateMacActivityPriorityTranslator
{
public CSUpdateMACActivityPriorityResponseType TestBusinessToService(IEntityTranslatorService service, object value)
{
return this.BusinessToService(service, value);
}
}
With that you can test the protected method through the test class and naturally call the method.
var translator = new TestUpdateMacActivityPriorityTranslator();
Assert.Catch<NotImplementedException>(() => translator.TestBusinessToService(null, null));
Related
I got a class which looks like below
public interface ILocationProvider
{
bool IsRequiredLocation (string type);
}
public class MyClass : IMyInterface
{
private readonly IEnumerable<ILocationProvider> _locationProvider;
public MyClass (ILocationProvider[] locationProvider)
{
_locationProvider = locationProvider;
}
public ILocationProvider ProvideRequireLocationObject(string type)
{
ILocationProvider location = _locationProvider.FirstOrDefault(x => x.IsRequiredLocation(type));
return location;
}
}
Now I am trying to write some tests for it. But I stuck passing the Mock<IEnumerable<ITransitReportCountryFlowProvider>> to constructor. Below my test code
[TestClass]
public class TMyClassTest
{
private Mock<IEnumerable<ILocationProvider>> _locationProvider = null;
private IMyInterface _myClass = null;
[TestInitialize]
public void InitializeTest ()
{
_locationProvider = new Mock<IEnumerable<ILocationProvider>>();
}
[TestMethod]
public void ProvideRequireLocationObject_Test1()
{
//Given: I have type as 'PMI'
string type = "PMI";
//When: I call MyClass object
_myClass = new MyClass(_locationProvider.Object); //wrong actual argument as the formal argument is an array of ILocationProvider
//_locationProvider.Setup(x => x.IsRequiredCountryFlow(It.IsAny<string>())).Returns(true); //how do I setup
ILocationProvider result = _myClass.ProvideRequireLocationObject(type);
//Then: I get a type of ILocationProvider in return
Assert.IsTrue(result is ILocationProvider);
}
}
Problem 1: The line _myClass = new MyClass(_locationProvider.Object) in above test class, as the constructor's formal argument is ILocationProvider[] so I cannot pass a mocking object of Mock<IEnumerable<ILocationProvider>>
Problem 2: If I change the line private readonly IEnumerable<ILocationProvider> _locationProvider; in above MyClass to private readonly ILocationProvider[] _locationProvider; I will not be able to mock it as because mock must be an interface or an abstract or non-sealed class.
Problem 3: How do I set up for _locationProvider.FirstOrDefault(x => x.IsRequiredLocation(type)); in my test method
Problem 4: How do I assert that my method ProvideRequireLocationObject is returning a type of ILocationProvider
First of all, you don’t need to mock the collection. Collections (arrays or lists) are tested well enough to trust on their implementation. Since your constructor expects an array, you need to pass an array. And the simplest way to do that is to simply pass an array. There is no reason to mock this at all.
Changing the implementation details of the class you are testing (as suggested in problem 2) will not change anything on the testing surface. Unit tests should always be independent from the internal implementation details anyway.
How do I assert that my method ProvideRequireLocationObject is returning a type of ILocationProvider
You don’t need to do that. The method has that return type, so the compiler will only accept an implementation where the method returns that type. You are guaranteed by the language that if there is a return value, then it’s of the ILocationProvider type. So you actually just need to check for null.
Taking your implementation, below is a possible way to test this. Note that you don’t actually need to mock this. You usually mock things when the actual implementation is too difficult to set up (e.g. has other dependencies) or when providing a testable implementation is too much work (e.g. an interface with lots of method but you only need one). In this case, I’m assuming that the ILocationProvider is easy to implement, so we’re going to create a test type for this:
[TestClass]
public class MyClassTests
{
[TestMethod]
public void ProvideRequireLocationObject_EmptyCollection()
{
// arrange
var providers = new ILocationProvider[] {};
var obj = new MyClass(providers);
// act
var result = obj.ProvideRequireLocationObject();
// assert
Assert.IsNull(result);
}
[TestMethod]
public void ProvideRequireLocationObject_NoRequiredLocation()
{
// arrange
var providers = new ILocationProvider[] {
new TestLocationProvider(false)
};
var obj = new MyClass(providers);
// act
var result = obj.ProvideRequireLocationObject();
// assert
Assert.IsNull(result);
}
[TestMethod]
public void ProvideRequireLocationObject_OneRequiredLocation()
{
// arrange
var providers = new ILocationProvider[] {
new TestLocationProvider(true)
};
var obj = new MyClass(providers);
// act
var result = obj.ProvideRequireLocationObject();
// assert
Assert.AreEqual(providers[0], result);
}
[TestMethod]
public void ProvideRequireLocationObject_OneRequiredLocationNotFirstInArray()
{
// arrange
var providers = new ILocationProvider[] {
new TestLocationProvider(false),
new TestLocationProvider(true),
new TestLocationProvider(false)
};
var obj = new MyClass(providers);
// act
var result = obj.ProvideRequireLocationObject();
// assert
Assert.AreEqual(providers[1], result);
}
[TestMethod]
public void ProvideRequireLocationObject_MultipleRequiredLocations()
{
// arrange
var providers = new ILocationProvider[] {
new TestLocationProvider(true),
new TestLocationProvider(true),
new TestLocationProvider(true)
};
var obj = new MyClass(providers);
// act
var result = obj.ProvideRequireLocationObject();
// assert
Assert.AreEqual(providers[0], result);
}
public class TestLocationProvider : ILocationProvider
{
public TestLocationProvider(bool isRequiredLocation)
{
IsRequiredLocation = isRequiredLocation;
}
public bool IsRequiredLocation { get; private set; }
}
}
Of course, you could expand those tests as necessary.
I believe are looking at it from the wrong angle. I think you don't need to mock the IEnumerable (Mock<IEnumerable<ITransitReportCountryFlowProvider>>) - IEnumerable has been testing front and back and besides you don't want to have to implement all its logic..
I think you should mock your own classes: Mock<ITransitReportCountryFlowProvider>
And pass a normal IEnumerable containing your mock in it
Something like:
[TestClass]
public class TMyClassTest
{
private Mock<ILocationProvider> _locationProvider = null;
private IEnumerable<ILocationProvider> _locationProviderCollection;
private IMyInterface _myClass = null;
[TestInitialize]
public void InitializeTest ()
{
_locationProvider = new Mock<IEnumerable<ILocationProvider>>();
_locationProviderCollection = new List<ILocationProvider> { _locationProvider };
}
[TestMethod]
public void ProvideRequireLocationObject_Test1()
{
//Given: I have type as 'PMI'
string type = "PMI";
//When: I call MyClass object
_myClass = new MyClass(_locationProviderCollection); //wrong actual argument as the formal argument is an array of ILocationProvider
.....
}
}
I'm trying to test some code I've written have run in to issues trying to mock a func using Machine.Fakes (which uses Moq under the hood). See the code below for an example.
public class RoutingEngine : IRoutingEngine
{
private readonly IMessageRouters _messageRouters;
public RoutingEngine(IMessageRouters messageRouters)
{
_messageRouters = messageRouters;
}
public void Route<T>(T inbound)
{
var messageRouters = _messageRouters.Where(x => x.CanRoute(inbound));
foreach(var router in messageRouters)
router.Route(inbound);
}
}
public class MessageRouters : IMessageRouters
{
public IList<IMessageRouter> _routers = new List<IMessageRouter>();
public IEnumerable<IMessageRouter> Where(Func<IMessageRouter, bool> func)
{
return _routers.Where(func);
}
public void Add(IMessageRouter messageRouter)
{
_routers.Add(messageRouter);
}
}
And the test is here
public class when_routing_a_message_with_fakes : WithSubject<RoutingEngine>
{
Establish that = () =>
{
Message = new MyMessage{ SomeValue= 1, SomeOtherValue = 11010 };
Router = The<IMessageRouter>();
Router.WhenToldTo(x => x.CanRoute(Message)).Return(true);
The<IMessageRouters>().WhenToldTo(x => x.Where(router => router.CanRoute(Message))).Return(new List<IMessageRouter> { Router });
};
Because of = () => Subject.Route(Message);
It should_do_route_the_message = () => Subject.WasToldTo(x => x.Route(Param.IsAny<MyMessage>()));
static MyMessage Message;
static IMessageRouter Router;
}
I get an unsupported expression for the above so I changed the where method on the IMessageRouters to the following:
public IEnumerable<IMessageRouter> Where(Expression<Func<IMessageRouter, bool>> func)
{
return _routers.Where(func.Compile());
}
Now I get this error
Object instance was not created by Moq.
Parameter name: mocked
Any ideas?
EDIT
So I tried writing another test without machine.fakes, as per Mocking methods with Expression<Func<T,bool>> parameter using Moq. Turns out it's an obvious problem. The func used in the real RoutingEngine is not being mocked
The<IMessageRouters>()
.WhenToldTo(x => x.Where(router => router.CanRoute(Param.IsAny<ProcessSkuCostUpdated>())))
.Return(new List<IMessageRouter> {Router});
The above has no bearing on the Where being executed at runtime and can't be as the func is compiled down to a private method at compile time. Seems like to mock the func, I need to push it up to an interface. Smells though as I'm pushing up internal behavior purely for testing.
I see two issues with your test code:
The expression you use for setting up the Where() call on IMessageRouters is too explicit. It should not care about what exact function is passed.
You are verifying whether Route() has been called on the Subject. Instead you should verify whether the Message has been passed to the IMessageRouter.
As an additional improvement, you can omit the Router field and use The<IMessageRouter>() directly.
[Subject(typeof(RoutingEngine))]
public class when_routing_a_message_with_fakes : WithSubject<RoutingEngine>
{
Establish that = () =>
{
Message = new MyMessage { SomeValue = 1, SomeOtherValue = 11010 };
The<IMessageRouter>().WhenToldTo(x => x.CanRoute(Message)).Return(true);
The<IMessageRouters>().WhenToldTo(x => x.Where(Param<Func<IMessageRouter, bool>>.IsAnything))
.Return(new List<IMessageRouter> { The<IMessageRouter>() });
};
Because of = () => Subject.Route(Message);
It should_route_the_message = () =>
The<IMessageRouter>().WasToldTo(x => x.Route(Message));
static MyMessage Message;
}
I see a way to avoid mocking the Func<> at all. I hope it's interesting to you :) Why not forget about the generalized Where(Func<>) method and provide the specific query method. You own the inbound messages and the router(s).
public class MessageRouters : IMessageRouters
{
public IList<IMessageRouter> _routers = new List<IMessageRouter>();
public IEnumerable<IMessageRouter> For<T>(T inbound)
{
return _routers.Where(x => x.CanRoute(inbound));
}
public void Add(IMessageRouter messageRouter)
{
_routers.Add(messageRouter);
}
}
The class under test becomes simpler (in signature, no Func<>).
public class RoutingEngine : IRoutingEngine
{
private readonly IMessageRouters _messageRouters;
public RoutingEngine(IMessageRouters messageRouters)
{
_messageRouters = messageRouters;
}
public void Route<T>(T inbound)
{
var messageRouters = _messageRouters.For(inbound);
foreach(var router in messageRouters)
router.Route(inbound);
}
}
I'm guessing you don't need to inspect the actual instance of the inbound message either, maybe you can get away with just a Type check, like
public IEnumerable<IMessageRouter> For<T>() { ... }
and
var messageRouters = _messageRouters.For<T>();
You don't have to mock any Func<>s now and you can just do an assert-was-called (or however that looks in Moq).
I have a class named "CollectionPager" which has a collection inside that of type List. I have a method "RetrieveList" which takes a "CollectionPager" as input and populates "List" in side that. This method doesn't return any value.
I need to mock a function which calls "RetrieveList". However, since it doesn't return any value, whatever input was fed into Mock is not taken into consideration and this collection(List) always has a count of 0.
Any possible ways to resolve this?
I guess you need the Callback (see also Moq quickstart) method to setup some logic when mocking a void function.
Here is sample test which demonstrates the usage:
var mock = new Mock<IRetrieveListService>();
mock.Setup(m => m.RetrieveList(It.IsAny<CollectionPager>()))
.Callback<CollectionPager>(p =>
{
p.List.Add("testItem1");
p.List.Add("testItem2");
});
var sut = new OtherService(mock.Object);
sut.SomeMethodToTest();
Assuming your classes looks like something like these:
public class CollectionPager
{
public CollectionPager()
{
List = new List<string>();
}
public List<string> List { get; private set; }
}
public interface IRetrieveListService
{
void RetrieveList(CollectionPager pager);
}
public class RetrieveListService : IRetrieveListService
{
public void RetrieveList(CollectionPager pager)
{
pager.List.Add("item1");
pager.List.Add("item2");
}
}
public class OtherService
{
private readonly IRetrieveListService retrieveListService;
public OtherService(IRetrieveListService retrieveListService)
{
this.retrieveListService = retrieveListService;
}
public void SomeMethodToTest()
{
var collectionPager = new CollectionPager();
retrieveListService.RetrieveList(collectionPager);
// in your test collectionPager.Item contains: testItem1, testItem2
}
}
I have a bit of a perfect storm that's preventing me from testing a class. The class is a RestClient that's wrapping an in-house HttpClient (which I cannot modify). The ExecuteMethod method on the HttpClient is void. It accepts an IHttpMethod, and it modifies this object based on the response from the server. I want to mock out ExecuteMethod so that it modifies the IHttpMethod for me. I'm trying to use Callback to achieve this, but it's not working.
Here's the code that sends the request:
var httpClient = this.httpClientFactory.CreateHttpClient();
httpClient.ExecuteMethod(method);
var response = this.GetResourceResponse<T>(method.ResponseBodyAsStream.AsString());
response.ResponseHeaders = method.ResponseHeaders;
response.Status = method.StatusCode.ToString();
response.StatusCode = (int)method.StatusCode;
return response;
And here's my attempt at mocking:
var mockHttpMethod = new Mock<IHttpMethod>();
mockHttpMethod.Setup(m => m.ResponseBodyAsStream).Returns(new MemoryStream(Encoding.UTF8.GetBytes("foo")));
var modifyHttpMethod = new Action<IHttpMethod>(m =>
{
m = mockHttpMethod.Object;
});
var mockHttpClient = new Mock<IHttpClient>();
mockHttpClient.Setup(c => c.ExecuteMethod(It.IsAny<IHttpMethod>()))
.Callback<IHttpMethod>(modifyHttpMethod);
var mockHttpClientFactory = new Mock<ILegalHoldHttpClientFactory>();
mockHttpClientFactory.Setup(f => f.CreateHttpClient()).Returns(mockHttpClient.Object);
var restClient = new RestClient(mockHttpClientFactory.Object);
When the modifyHttpMethod action is executed, I observe two things, both of which I expect:
The incoming IHttpMethod (m) has the properties I expect it to have.
After assigning the mock object to m, it contains the stubbed values that I setup in my test.
However, after the callback is executed and control is returned to my application code, my method variable still has its old values that I saw in step 1 above, which causes a null reference exception when trying to read method.ResponseBodyAsStream.
Is what I'm trying to do even achievable? If so, how? Thanks!
I've replicated your setup vis a vis mocking, and can't find any issues with it:
public interface IHttpMethod
{
MemoryStream ResponseBodyAsStream { get; set; }
}
public interface IHttpClient
{
void ExecuteMethod(IHttpMethod method);
}
public class HttpClient : IHttpClient
{
#region IHttpClient Members
public void ExecuteMethod(IHttpMethod method)
{
}
#endregion
}
public class Factory
{
public virtual IHttpClient CreateHttpClient()
{
return new HttpClient();
}
}
public class ClassUnderTest
{
private readonly Factory _factory;
public ClassUnderTest(Factory factory)
{
_factory = factory;
}
public string GetResponseAsString(IHttpMethod method)
{
var myClient = _factory.CreateHttpClient();
myClient.ExecuteMethod(method);
return method.ResponseBodyAsStream.ToString();
}
}
[TestClass]
public class ScratchPadTest
{
[TestMethod]
public void SampleTest()
{
var mockHttpMethod = new Mock<IHttpMethod>();
mockHttpMethod.Setup(x => x.ResponseBodyAsStream).Returns(new MemoryStream(Encoding.UTF8.GetBytes("foo")));
var modifyHttpMethod = new Action<IHttpMethod>(m =>
{
m = mockHttpMethod.Object;
});
var mockHttpClient = new Mock<IHttpClient>();
mockHttpClient.Setup(c => c.ExecuteMethod(It.IsAny<IHttpMethod>())).Callback<IHttpMethod>(modifyHttpMethod);
var myFactoryStub = new Mock<Factory>();
myFactoryStub.Setup(f => f.CreateHttpClient()).Returns(mockHttpClient.Object);
var myCut = new ClassUnderTest(myFactoryStub.Object);
Assert.IsNotNull(myCut.GetResponseAsString(mockHttpMethod.Object));
}
}
That test passes, meaning that the memory stream is not null (otherwise an exception would be generated). The only X factor that I can see is your AsString() extension method (I'm assuming that's an extension method as intellisense doesn't show it to me on MemoryStream). Could your problem be in there?
And, by the way, what you're trying to do is almost certainly achievable with Moq.
I have the following method;
public class MyClass
{
public Repository UserRepository { get; set; }
public void CreateUser(Message someMsg)
{
if (someMsg.CanCreate)
{
var obj = new object();
UserRepository.Save(obj)
}
}
}
In my test case, I used Moq to mock out the ObjRepository and I wanted to to call verify on the "Save()" method. However, the save method takes in a object that is created within the method under test, which I cannot mock.
Is there anyway around this using Moq? I am doing this wrong?
You can have the following setup on your mock:
objRepMock.Setup(or => or.Save(It.IsAny<object>()).Callback(obj => {
// Do asserts on the object here
}
marcind got the ball rolling but I thought I'd put more code in. Your test would look like this:
var objMock = new Mock<Repository>();
objMock.Setup(x=>x.Save(It.IsAny<object>)).Verifiable();
var myclass = new MyClass{Repository = objMock.object};
var mymessage = new Mock<Message>();
myclass.CreateUser(mymessage.object);
objMock.Verify(x=>x.Save(It.IsAny<object>), Times.AtLeastOnce);
You could use dependency injection.
public Repository ObjRepository { get; set;}
public void doStuff()
{
var obj = new object();
doStuff(obj);
}
public void doStuff(Object obj)
{
ObjRepository.Save(obj)
}