New to unit testing & Moq. I have a WPF client app which hooks into a WCF service via HttpBinding. I have a test class in MSTest and I'm mocking my service with Moq like so:
[TestClass]
public class ArticleDataGridTests
{
//Mock channel for WCF service. Moq mocking framework.
Mock<IIsesServiceChannel> channelMock = new Mock<IIsesServiceChannel>();
[TestMethod]
public void LoadArticleTitlesListTestValid()
{
channelMock.Setup(c => c.GetArticleTitles());
ArticleDataGridViewModel articleDataGridViewModel = new ArticleDataGridViewModel(channelMock.Object);
articleDataGridViewModel.LoadArticleTitlesList();
channelMock.Verify(c => c.GetArticleTitles(), Times.Once());
}
}
}
Here is the method LoadArticleTitles list that's being invoked in the ViewModel. ArticlesTitleList is a List<string>:
public void LoadArticleTitlesList()
{
ArticleTitlesList = new List<string>(IsesService.GetArticleTitles());
}
Obviously this test fails. I get a null exception on the 'collection'. How do I mock this list of strings for my test or should I not be writing void method stubs with WCF service method calls which return lists nested inside them in the first place? Thanks
You need to return data after setup:
var listOfStrings = new List<string>{{"test1"}};
channelMock.Setup(c => c.GetArticleTitles()).Returns(listOfStrings);
Had to pass in an array of string rather than a List<string> as WCF looks like a method that returns a .ToList() is stubbed out as returning an []string in the boiler plate code. Therefore passing in a list of string gives an overloaded method invalid argument exception. Ended up with this:
var ArticleTitlesList = new string[] { "LoadArticleTitlesListTestValid" };
channelMock.Setup(c => c.GetArticleTitles()).Returns(ArticleTitlesList);
Related
Scenario:
We are in the lovely scenario of a terrible data source that requires an arcane syntax. We have built our "repository" layer to translate simple parameters (primitive values) into the correct syntax for the destination.
We would like to unit test that:
The correct filters have been applied (can be done by checking the string that the repo's helper methods create)
The (mocked) remote data source is called exactly once
The (mocked) data we have defined the remote data source as returning is passed back as the return value when we call the repo.
For example
var expectedReturn = new List<Product> { new Product { StockNumber = "123" } };
provider.Setup(x => x.Run(It.IsAny<Func<IRemoteClient, Task<List<Product>>>>(),
It.IsAny<string>())).ReturnsAsync(expectedReturn);
Moq is failing on the Setup line with a NotSupportedException. I've read probably a dozen or more SO posts and can't find out why it doesn't work.
In normal usage, the Repo will use something like:
provider.Run(x => x.GetAsync<List<Product>>(requestBuilder.Request), "foo")
Definition of run in provider interface:
Task<T> Run<T>(Func<IRemoteClient, Task<T>> action, string name);
Since the requestBuilder is injected as well, we can easily evaluate that the request is built correctly as far as the number and type of parameters, but we can't run the test at all because the Mock call fails the setup and so we never get there.
I am using Moq 4.9.0 and have tested this both on .NET Core 2.1, as well as inside LINQPad using the .NET Framework. It compiles and runs for me without any problems. I am able to run the mock setup, and I am also able to call the mocked method on the mock object, and retrieve the expected return result.
The following is my test code:
class Program
{
static void Main(string[] args)
{
var expectedReturn = new List<Product> { new Product { StockNumber = "123" } };
var provider = new Mock<IProvider>();
provider
.Setup(x => x.Run(
It.IsAny<Func<IRemoteClient, Task<List<Product>>>>(),
It.IsAny<string>()))
.ReturnsAsync(expectedReturn);
var result = provider.Object.Run(client => client.GetAsync<List<Product>>(null), "foo");
Console.WriteLine(result.Result[0].StockNumber);
}
}
public interface IProvider
{
Task<T> Run<T>(Func<IRemoteClient, Task<T>> action, string name);
}
public interface IRemoteClient
{
Task<T> GetAsync<T>(object request);
}
public class Product
{
public string StockNumber { get; set; }
}
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.
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.
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'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
}