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.
Related
public void Pay()
{
// some insert db code
// ...
// Call Bank api
BankApi api = new BankApi();
int result = api.pay();
if(result == 1)
{
//...
}
else
{
//...
}
}
I dont want to call api in unit test. How to mock the pay method without modify inner code (such as the line new BankApi() code)?
Its possible to mock your BankApi class without changing any of your legacy code, you just need a unit testing framework that allows you to mock concrete classes.
for example a test for your method with Typemock :
[TestMethod]
public void ExampleTest()
{
//fakes the next BankApi instace
var handler = Isolate.Fake.NextInstance<BankApi>();
//change the pay method behavior
Isolate.WhenCalled(() => handler.pay()).WillReturn(1);
new ClassUnderTest().Pay();
}
First, as stated, you should create an Interface.
public interface IBankApi
{
int pay();
}
Then, what you can do is mock this interface like this (I'm using Moq "Mock you" here, you will need to add the NuGet package "Moq" as reference to your application, and you could use other mocking libraries of course)
apiMock = new Mock<IBankApi>();
just after that you will tell what this call should return (that would be actual mocking)
apiMock.Setup(x => x.pay()).Returns(1); //
Then, this api "pseudo object", can be used by using apiMock.Object
Now , this information I just gave you doesn't directly solve your problem.
As stated in the comments, you need a better uncoupling of your code.
You need, for example, some kind of "dependency injection" to allow for such a uncoupling.
Here is a simple example of how it can be done :
public class ClassThatUsesYourBankApi
{
private readonly IBankApi _api;
// the constructor will be given a reference to the interface
public ClassThatUsesYourBankApi (IBankApi api)
{
// here you could check for null parameter and throw exception as needed
this._api = api;
}
// this method can now be tested with the mock interface
public void MethodThatUseTheApi()
{
int result = this._api.pay();
if (result == 1)
{
// some things that happens
}
else
{
// some other thing
}
}
}
How to unit test that method :
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
[TestClass]
public class TestMyMethod
{
[TestMethod]
public void MyMethod_WithBankApiReturns1_ShouldHaveThingsThatHappens()
{
// Arrange
var apiMock = new Mock<IBankApi>();
apiMock.Setup(api => api.pay())
.Returns(1);
var myObject = new ClassThatUsesYourBankApi(apiMock.Object);
// Act
int result = myObject.MethodThatUseTheApi();
// Assert
// Here you test that the things that should have happened when the api returns 1 actually have happened.
}
}
The key thing to understand here, is that you must not instantiate the api you need to mock in the method you want to test
In other words, "uncoupling" your method with your api is done by programming to an interface, and code such as you don't have
var api = new BankApi()
directly in the method you want to unit test.
I showed a way to do that, and there are other.
I recently took a .Net project over which exposes DAOs from a Microsoft SQL Database via ServiceStack(3.9.71) REST API. Since I am gonna refactor some parts I want to unit test (at least) all servicestack services. For a better understanding I quickly draft how the implementation works.
Each Service contains a property of type DBService which encapsulates all database accesses of all services. Unfortunately this is a concrete class which makes it hard to mock. The DI.Container wrappes ServiceStack's IOC.
public class SomeService : Service
{
public DBService { get { return DI.Container.Resolve<DBService>(); } }
public object Get(SomeDataClass class)
{
var response = DBService.SomeServiceGet();
return response;
}
// other code omitted
}
The DBService looks like this (draft):
public class DBService
{
public IDbConnectionFactory DBFactory { get { return DI.Container.Resolve<IDbConnectionFactory>(); } }
public SomeServiceResponse SomeServiceGet()
{
//DB Access here...
// ...
}
public SomeOtherServiceResponse SomeOtherServiceGet()
{
//...
}
// following about 30 other methods for all the services (POST,GET,PUT etc)
}
I read the detailed response to this question but I was not able to create and initialize a BasicAppHost in ServiceStack 3.9.71 since it immediately threw a System.TypeLoadExceptionMethod 'get_VirtualPathProvider'.
On the other hand I was thinking that I do not actually need a BasicAppHost. I just have to unit test the DBService and then the servicestack services with a somehow mocked DBService. The only problem I have is that DBService is not an interface and that I am actually not sure how to deal (mock) with the SQL database and the IOC.
[UPDATE]
Unfortunately I am still not able to test a service since I can not just new the service in my test. If I do so I get:
System.TypeLoadExceptionCould not load type 'ServiceStack.ServiceHost.IService' from assembly
Here is my test:
[Fact]
public void SomeDataTest()
{
var serviceUnderTest = new SomeService();
var response = serviceUnderTest.Get(new SomeDataClass());
Assert.NotNull(response);
}
I guess the problem is that the services strongly uses alot of properties which are injected via the IOC. How can I mock that? Creating a BasicAppHost and retrieving the service from there also does not work which I already mentioned.
If you are just testing your service class, then you can directly mock any dependencies:
[Fact]
public void SomeDataTest(
{
var serviceUnderTest = new SomeService();
var logger = new Mock<ILogger>(); // Rhino mocks fashion.
serviceUnderTest.Logger = logger.Object;
var response = serviceUnderTest.Get(new SomeDataClass());
Assert.NotNull(response);
}
There's an page in their older docs here about integration testing in case you want to test the AppHost
Edit: there's an example of mocking the service dependencies here.
New to unit testing. I have a WPF client app hooked into a WCF service via basicHttpbinding. Everything works great. I'm using simple constructor Dependency Injection in my viewModel, passing in an IServiceChannel which I then call me service methods on e.g:
IMyserviceChannel = MyService;
public MyViewModel(IMyServiceChannel myService)
{
this.MyService = myService;
}
Private void GetPerson()
{
var selectedPerson = MyService.GetSelectedPerson();
}
I have then added an MS Test project in the client app and I'm trying to use Moq to mock my service:
[TestMethod]
public void GetArticleBody_Test_Valid()
{
// Create channel mock
Mock<IIsesServiceChannel> channelMock = new Mock<IIsesServiceChannel>(MockBehavior.Strict);
// setup the mock to expect the Reverse method to be called
channelMock.Setup(c => c.GetArticleBody(1010000008)).Returns("110,956 bo/d, 1.42 Bcfg/d and 4,900 bc/d. ");
// create string helper and invoke the Reverse method
ArticleDataGridViewModel articleDataGridViewModel = new ArticleDataGridViewModel(channelMock.Object);
string result = channelMock.GetArticleBody(1010000008);
//Assert.AreEqual("cba", result);
//verify that the method was called on the mock
channelMock.Verify(c => c.GetArticleBody(1010000008), Times.Once());
}
The test is failing with a System.NullReferenceException. Object reference not set to an instance of an object. at the method invocation here:
string result = articleDataGridViewModel.IsesService.GetArticleBody(1010000008);
so I'm wandering whether this is the best way to approach or am I better somehow mocking an isolated part of the viewModel which is applicable to the test?
The NullReferenceException is mybe thrown because you use MockBehavior.Strict. The documentation says:
Causes this mock to always throw an exception for invocations that don't have a corresponding setup.
Maybe the constructor of ArticleDataGridViewModel calls other methods of the service which you haven't set up.
Another issue is, that you are calling the mocked method directly. Instead you should call a method of your view model, which calls this method.
[TestMethod]
public void GetArticleBody_Test_Valid()
{
// Create channel mock
Mock<IIsesServiceChannel> channelMock = new Mock<IIsesServiceChannel>();
// setup the mock to expect the Reverse method to be called
channelMock.Setup(c => c.GetArticleBody(1010000008)).Returns("110,956 bo/d, 1.42 Bcfg/d and 4,900 bc/d. ");
// create string helper and invoke the Reverse method
ArticleDataGridViewModel articleDataGridViewModel = new ArticleDataGridViewModel(channelMock.Object);
string result = articleDataGridViewModel.MethodThatCallsService();
//Assert.AreEqual("cba", result);
//verify that the method was called on the mock
channelMock.Verify(c => c.GetArticleBody(1010000008), Times.Once());
}
Besides that I think there is no problem with your approach. Maybe the view model violates the single responsibility principle and does more than it should, but that's hard to tell on the basis of your code example.
EDIT: Here's a full example of how you could test something like this:
public interface IMyService
{
int GetData();
}
public class MyViewModel
{
private readonly IMyService myService;
public MyViewModel(IMyService myService)
{
if (myService == null)
{
throw new ArgumentNullException("myService");
}
this.myService = myService;
}
public string ShowSomething()
{
return "Just a test " + this.myService.GetData();
}
}
class TestClass
{
[TestMethod]
public void TestMethod()
{
var serviceMock = new Mock<IMyService>();
var objectUnderTest = new MyViewModel(serviceMock.Object);
serviceMock.Setup(x => x.GetData()).Returns(42);
var result = objectUnderTest.ShowSomething();
Assert.AreEqual("Just a test 42", result);
serviceMock.Verify(c => c.GetData(), Times.Once());
}
}
Without access to your viewmodel, there's only so much help that we can provide you.
However, this code:
Mock<IIsesServiceChannel> channelMock = new Mock<IIsesServiceChannel>(MockBehavior.Strict);
...
ArticleDataGridViewModel articleDataGridViewModel = new ArticleDataGridViewModel(channelMock.Object);
...
string result = articleDataGridViewModel.IsesService.GetArticleBody(1010000008);
Does not set up your IsesService. If it is not set up in your constructor, that means the IsesService is a null reference. You can't call a method on a null object.
Consider mocking out at a higher level of abstraction then the tight coupling you have with the tool your using.
Perhaps your view-model should rely on services and not a detail of the tool that your using (i.e. IIsesServiceChannel).
Here's an example:
Construct testable business layer logic
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.
I'm new to Moq and unit testing. I have been doing a unit test and this is the following code:
private Mock<IServiceAdapter> repository;
[TestInitialize]
public void Initialize()
{
repository= new Mock<IServiceAdapter>();
}
[TestMethod()]
public void SaveTest()
{
//Setup
string Name = "Name1";
string Type = "1";
string parentID = null;
repository.Setup(x => x.Save(Name , Type, parentID)).Returns("Success").Verifiable();
//Do
var result = repository.Object.Save(Name , Type, parentID);
//Assert
repository.Verify();
}
My problem is that the test will always return the string that I put in the Returns parameter, in other words, it will always return "success" or whatever I write in its place. I guess thats not right because thats not the real behavior of the service. Anyone knows how I can mirror the real behavior of the "Save" service I'm trying to test? So lets say, if the return string is different from the service method,then the test should fail.
Edited
The ServiceAdapter interface its just a wrapper for a Web Service which I call like a REST Service. It's a Web Forms Project.
I'm doing something like in this post
How to mock a web service
Should I create something like a FakeController with Dependency Injection to make it work?
You are testing mock here, which gives you nothing (because this mock is not used in your real application). In unit-testing you should create and test your real objects, which exist in your real application (i.e. interface implementations). Mocks used for mocking dependencies of objects under test.
So, mock of service adapter will be useful for tests of object, which uses that adapter, e.g. some controller tests:
private FooController _controller; // object under test, real object
private Mock<IServiceAdapter> _serviceAdapter; // dependency of controller
[TestInitialize]
public void Initialize()
{
_serviceAdapter = new Mock<IServiceAdapter>();
_controller = new FooController(_serviceAdapter.Object);
}
[TestMethod()]
public void SaveTest()
{
// Arrange
string name = "Name1";
string type = "1";
string parentID = null;
_serviceAdapter.Setup(x => x.Save(name , type, parentID))
.Returns("Success").Verifiable();
// Act on your object under test!
// controller will call dependency
var result = _controller.Bar(name , type, parentID);
// Assert
Assert.True(result); // verify result is correct
_serviceAdapter.Verify(); // verify dependency was called
}