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());
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With