I am developing a new MVC 5 Application. I have an Integration Layer in my project where I have a service reference to an external web service.
I then created a interface that has some methods - I then have a service class which looks something like below:
public class MyService : IMyService
{
private readonly ExternalServiceClient _serviceClient;
public MyService()
{
_serviceClient = new ExternalServiceClient ("WSHttpBinding_IMyService");
}
public string GetName(Coordinate[] coordinates)
{
string name = string.Empty;
name = _serviceClient.GetInformationsForCoordinates(coordinates);
return name;
}
Note this is stripped down and in reality will add try catch block with Exception Handling, etc
I have a Integration.Tests project for Unit Testing of the integration layer. What is the best practice way of testing the GetName method. Should I add another Service Reference to the endpoint of the service in the Tests project or if we are using Moq can I create a instance of my actual service that the Web Layer for example will call - and how would that be done?
The best practice for your situation lies in your architecture design.
Your service obviously depends on ExternalServiceClient, and you're intantiating it inside of your MyService class, which doesn't allow you to switch the dependency easily, causing you headaches when it's time to test it.
The real question should be:
How may I design my service in order to make it easily testable?
And the answer is Dependency Injection.
Because you will be able to mock MyService dependency, you will be able to thoroughly test it and be able to certify, by red-green refactoring, that your service works flawlessly.
In my humble opinion, your class should like this:
public class MyService : IMyService {
public MyService(ExternalServiceClient serviceClient) {
externalServiceClient = serviceclient;
}
public string GetName(Coordinate[] coordinates) {
string name = string.Empty;
name = externalServiceClient.GetInformationForCoordinates(coordinates);
return name;
}
private readonly ExternalServiceClient externalServiceclient;
}
This way, you will be able to replace your dependency at your will, hence the use of a mock.
Using NUnit and Moq, you could test your service as follows:
[TestFixture]
public class MyServiceTests {
[TestFixture]
public class GetCoordinates : MyServiceTests {
// Given
string expected = "Name";
Coordinate[] coordinates = new Coordinate[] { ... }
externalServiceClientMock.Setup(esc => esc.GetInformationForCoordinates(coordinates)).Returns(expected);
// When
string actual = myService.GetName(coordinates);
// Then
externalServiceClientMock.Verify(esc => esc.GetInformationCoordinates(coordinates));
Assert.AreEqual(expected, actual);
}
[SetUp]
public void MyServiceSetup() {
externalServiceClientMock = new Mock<ExternalServiceClient>("WSHttpBinding_IMyService");
myService = new MyService(externalServiceClientMock.Object);
}
private Mock<ExternalServiceClient> externalServiceClientMock;
private MyService myService;
}
In general, it is good practice (as you have readonly semantic for ExternalServiceClient) to have parametrized constructor to be able to inject the dependency on object construction. Then you can inject the mock in your test case.
In your case, if there is interface(s) that implemented in ExternalServiceClient
private readonly ExternalServiceClient _serviceClient;
public MyService(IExternalServiceClient serviceClient)
{
_serviceClient = serviceClient;
}
Then use it as:
var service = new MyService(new ExternalServiceClient ("WSHttpBinding_IMyService"));
and in test
IExternalServiceClient mockObject = //construct mock with desired behabiour then pass to ctor
var service = new MyService(mockObject);
If there is no implemented interfaces and ability to add it (since it is external), you must do some tricks with virtuallity.
Related
I have the following Controller interface:
public interface IInformationController
{
string GetStoredInformation();
string GetInformation();
}
The controller class is the following:
public class InformationController : ControllerBase, IInformationController
{
private InformationProvider1 InformationProvider1;
private InformationProvider2 InformationProvider2;
private IBasicRepository repository;
public InformationController(IBasicRepository basicRepository)
=> repository = basicRepository;
public string GetStoredInformation()
=> repository.GetStoredInformation();
public string GetInformation()
=> $"Information is {informationProvider1.GetInformationHeader()}, Information detail is {informationProvider2.GetInformationDetail()}";
}
I intend to create a unit test for the InformationController with xUnit and Moq.
This is my test class:
public class InformationControllerTest
{
public InformationControllerTest()
{
repositoryMock = new Mock<IBasicRepository>();
repositoryMock.Setup(repository => repository.GetStoredInformation()).Returns("Stored information");
SUT = new InformationController(repositoryMock.Object);
}
[Fact]
public void GetStoredInformation_Returns_Stored_Information()
{
string result = SUT.GetStoredInformation();
Assert.Equal("Stored information", result);
}
[Fact]
public void GetInformation_Returns_Valid_Information()
{
string result = SUT.GetInformation(); //TODO: how to avoid the usage of actual provider implementations?
Assert.Equal("Information is Header1, Information detail is Detail1", result);
}
}
As you can see, there are private providers. Unfortunately they are external dependencies and can't easily be introduced via dependency injection.
How should I mock their actual calls? Should I mock the controller method (which imho should invalidate the process of testing the actual controller)? Should I try to get them via dependency injection?
The unit test is exposing the short comings of your current design, which is tightly coupling to external dependencies or implementation concerns.
Dependencies should be explicitly injected into their dependents
Methods and classes should explicitly require (typically through method parameters or constructor parameters) any collaborating objects they need in order to function correctly.
Reference Explicit Dependencies Principle
public class InformationController : ControllerBase, IInformationController {
private IInformationProvider1 informationProvider1;
private IInformationProvider2 informationProvider2;
private IBasicRepository repository;
public InformationController(IBasicRepository basicRepository,
IInformationProvider1 informationProvider1,
IInformationProvider2 informationProvider2) {
repository = basicRepository;
this.informationProvider1 = informationProvider1;
this.informationProvider2 = informationProvider2
}
public string GetStoredInformation()
=> repository.GetStoredInformation();
public string GetInformation()
=> $"Information is {informationProvider1.GetInformationHeader()}, Information detail is {informationProvider2.GetInformationDetail()}";
//...
}
Create abstractions and implementations for those external dependencies, then register them with the DI container so that they can be resolved and properly provided to the controller at run-time. This will now allow them to also be tested in isolation without undesired side effects from their actual implementations.
I am doing unit testing of controllers in my asp.net core project. In one section, there is a code like this instantiating an object of class and calling its method.
public class ControllerNameController: ControllerBase{
private IDependency _dependency;
public ControllerNameController(IDependency dependency){
_dependency = dependency
}
[HttpGet, Route("Get")]
public ActionResult<dynamic> Get()
{
......
string someString = "abcd";
ClassOne classOneObject = new ClassOne(_dependency);
classOneObject.ClassOneMethod(someString);
..........
return .....
}
}
I am being unable to mock this function. How can I do this?
You will have to change the code. One of the major advantages of unit testing is not to protect you from errors but to help you write better code.
The ErrorLogHelper is either a service or a horizontal aspect.
Moq is by design made to mock interfaces or virtual methods. To do that, you need to somehow inject this dependency to the target object.
In this case you need to make this a service dependency, have it implement an interface and inject via property or constructor.
Inline initialization means that the code must run with the unit test, as it is an integral part of the code flow.
private IHostingEnvironment _hostingEnvironment;
public IErrorLogHelper logHelper
public ControllerNameController(IHostingEnvironment hostingEnvironment, IErrorLogHelper logHelper){
_hostingEnvironment = hostingEnvironment;
this.logHelper = logHelper;
}
And in your catch
catch (Exception ex)
{
string controllerInfo = controller.ActionDescriptor.DisplayName;
logHelper.ErrorLogToFile(controllerInfo, ex);
}
Background
My application is consuming a WCF service via proxyies. I have to unit test my implementation, that it consume the service and processing are done correctly.
Method to be Tested
public class MyClass
{
private ManagerServiceClientImpl myclient;
public void MethodToBeTested();
{
var result = GetServiceData();
if(result!=null)
//some processing
}
}
private MyObject GetServiceData()
{
myclient = ServiceLocator.Current.GetInstance<ManagerServiceClientImpl>();
if(myclient.ConnectToService() && myclient.MyServiceClient.IsConnected)
return myclient.GetData();
else
return null;
}
This is provided by external source, so I have no right to modify it
public class ManagerServiceClientImpl
{
public ServiceClient MyServiceClient { get; private set; }
public bool ConnectToService()
}
How would I mock the ManagerServiceClientImpl it doesn't have interface or methods are not marked as virtual
What i tried so far.
[TestMethod]
public void IsServiceConnected_GetData()
{
//Arrange
ManagerServiceClientImpl clientImpl =
MockRepository.GenerateMock<ManagerServiceClientImpl>();
ServiceLocator.Expect(x => x.GetInstance<ManagerServiceClientImpl>())
.Return(clientImpl);
var testData= new MyObject
{
ID = "Test1",
Name ="test",
}
//Act
_myClass.MethodToBeTested();
//Assert
stubService.AssertWasCalled(h => h.SaveAllChanges());
}
Note: Using Rhino.Mocks. Its my first time using Rhino mocks
As Amittai Shapira mentioned you can mock it without an interface by using unit testing frameworks that support it, i'm using Typemock Isolator and i created an example test for your code:
I've created an instance of MyClass and used a feature of Typemock to mock Non-Public methods to change the return value for GetServiceData
[TestMethod]
public void TestMethod1()
{
var testData = new MyObject
{
ID = "Test1",
Name = "test",
};
var realObj = new MyClass();
Isolate.NonPublic.WhenCalled(realObj, "GetServiceData").WillReturn(testData);
Isolate.NonPublic.WhenCalled(realObj, "SaveAllChanges").CallOriginal();
realObj.MethodToBeTested();
Isolate.Verify.NonPublic.WasCalled(realObj, "SaveAllChanges");
}
In order to use RhinoMocks (or Moq, or any other "constrained" mocking framework), the type you are mocking must support inheritance on the members you want to mock. This means it must either be an interface, or the members must be virtual/abstract. Without that, these frameworks cannot do what they need to do to generate a proxy middle-man at runtime. For more details, see my blog post on how .NET mocking frameworks work under the hood: https://www.wrightfully.com/how-net-mocking-frameworks-work
What you could do is create methods in your own class that wrap the other service such that you could mock your methods and have them return whatever you need, completely bypassing the service.
Hi I am just writting my first unit test and I have a case where I have to test if the correct mapper is returned.
This is my code:
public UserPersonalDetailsDTO GetUserPersonalDetails(int personId)
{
var mapper = ServiceLocator.GetInstance<IMappingService<UserPersonalDetails, UserPersonalDetailsDTO>>();
var userPersonalDetails = UnitOfWork.PersonData.GetUserPersonalDetails(personId);
var userPersonalDetailsDTO = mapper.Map(userPersonalDetails);
return userPersonalDetailsDTO;
}
How would I test if I am getting the correct mapper?
EDIT
I forgot to mention that I am using Unity as my DI Framework this si my constructor:
public ProfileService(IEConnectUow uow, IValidationService validationService, IServiceLocator serviceLocator)
: base(uow, serviceLocator)
{
m_ValidationService = validationService;
}
My CUrrent class inherits from a BaseCLass that have this properties:
protected IEConnectUow UnitOfWork { get; set; }
protected IServiceLocator ServiceLocator { get; set; }
public BaseService(IEConnectUow uow, IServiceLocator serviceLocator)
{
UnitOfWork = uow;
ServiceLocator = serviceLocator;
}
That code is really difficult to unit test. At least two of the dependencies come in via statics (ServiceLocator, UnitOfWork).
I would refactor the code to the following
public class Whatever {
private IMappingService<UserPersonDetails, UserPersonalDetailsDTO> mapper;
private PersonData personData;
public Whatever(IMappingService<UserPersonDetails, UserPersonalDetailsDTO> mapper,
PersonData personData) {}
public UserPersonalDetailsDTO GetUserPersonalDetails(int personId) {
var userPersonalDetails = personData.GetUserPersonalDetails(personId);
var userPersonalDetailsDTO = mapper.Map(userPersonalDetails);
return userPersonalDetailsDTO;
}
}
In the whatever class you can now test the interactions with the objects you pass in. You don't want to be testing that the right mapper is returned in this class. In a unit test, ideally you only want to test the logic of the class and its interactions with dependencies. In this case, I'd simply test the interactions. GetUserPersonalDetails talks to the PersonData object, and uses the Mapper to get the result.
Testing that you get the right mapper isn't the responsibility of this class. Factor that logic out somewhere (perhaps starting with ServiceLocator) into its own class with its own dependencies and verify it does what you want.
Your ServiceLocator is some factory class. If the ServiceLocator is writen by you, you can test is seperately. If it is a libary class, the libary is tested (assumue). You can test is the GetInstance<IMappingService<UserPersonalDetails, UserPersonalDetailsDTO>>(); method is called for the correct types. This can be done with a mocking framework. You make a mock for the GetInstance method and then check if it is called, you know the GetInstance method is right because you have tested it somewhere else.
My test whould look like (pseudo code):
Make mock ServiceLocator.GetInstance
Make mock UnitOfWork.PersonData.GetUserPersonalDetails
Make mock mapper.Map
call GetUserPersonalDetails(int personId)
check if ServiceLocator.GetInstance was correct
The using below hits an external resource that I do not want to actually hit. I want to test someResult and the code that uses it, but every time I run my unit test, this code still tries to hit the real web service. How do I use moq to fake the real call to the web service, but not mock the rest of the code within the using?
public IMyInterface.SomeMethod()
{
// hits a web service
using ( mySoapClient client = new mySoapClient() )
{
var someResult = client.DoSomething();
...
...
}
}
[TestMethod()]
public void SomeMethodTest()
{
IMyInterface target = new MyInterface();
target.SomeMethod();
// Assert....
}
You need to decouple the web service implementation from the consumer
public class ClassIWantToTest
{
public ClassIWantToTest(IServiceIWantToCall service) {}
public void SomeMethod()
{
var results = service.DoSomething();
//Rest of the logic here
}
}
Now you can use Moq to mock the IServiceIWantToCall in order to test the logic of SomeMethod
To add to pickles' answer, I created an interface for my current service calls named IService. I then created a ServiceMock class that inherits the interface and added a global variable named _service. In the constructor I instantiate the mock service and set up all the methods of the interface as such:
public class ServiceMock : IService
{
Mock<IService> _serviceMock;
public ServiceMock()
{
_serviceMock = new Mock<IService>();
_serviceMock.Setup(x => x.GetString()).Returns("Default String");
SomeClass someClass = new SomeClass();
someClass.Property1= "Default";
someClass.Property2= Guid.NewGuid().ToString();
_serviceMock.Setup(x => x.GetSomeClass()).Returns(someClass);
}
public string GetString()
{
return _serviceMock.Object.GetString();
}
public License GetSomeClass()
{
return _serviceMock.Object.GetSomeClass();
}
}
You then inject this class into your code instead of the actual web service. It will return the values you set it up to return. You can now test without depending on your web service.
You first have to be able to inject the web service. Creating a new one inside SomeMethod() "tightly couples" the method to the production code; you can't dynamically tell it to create something other than a mySoapClient.
Since you want to create and destroy them, might I suggest that the code you want to test accept a Func<IMySoapClient> as a method parameter or as a constructor parameter. It would look something like this:
public IMyInterface.SomeMethod(Func<IMySoapClient> clientFactory)
{
// hits a web service
using ( mySoapClient client = clientFactory() )
{
var someResult = client.DoSomething();
...
...
}
}
... or:
public class MyClass:IMyInterface
{
private Func<IMySoapClient> MySoapClientFactoryMethod;
public MyClass(Func<IMySoapClient> clientFactoryMethod)
{
MySoapClientFactoryMethod = clientFactoryMethod;
}
...
public IMyInterface.SomeMethod()
{
// hits a web service
using ( mySoapClient client = MySoapClientFactoryMethod() )
{
var someResult = client.DoSomething();
...
...
}
}
}
Now, when you create the object you are trying to test, you define a function that generates the appropriate Moq mock of the Soap service, which has the behavior you would expect from the real client without the side effects (including being able to tell that the code Dispose()d of the client), and pass that function into the class or method that you're testing. In production, you could simply define the function as ()=>new mySoapClient(), or you could set up an IoC framework and register mySoapClient as an IMySoapClient, then also register MyClass; most IoC frameworks are smart enough to see the delegate as a parameter and generate the method that injects the registered dependency.