I am trying to perform an Unit Testing(Integration Test using Moq) in my code using MVP-VM patterns. I have a view, a viewmodel, and a presenter.
The presenter holds the actual functionality of my UIs.
The way I was trying to test my presenter is, like following.
public interface IMockView : IRealView
{
event EventHandler ButtonClickedEvent;
}
public interface IMockViewModel : IRealViewModel
{ }
public class MockPresenter : RealPresenter
{
private IMockView _view;
private IMockViewModel _viewModel;
public MyProperty { get; set; }
public MockPresenter (IMockView view, IMockViewModel viewModel)
:base(view, viewModel)
{
_view = view;
_viewModel = viewModel;
view.ButtonClickedEvent += (s, e) =>
{
//Do Something
this.MyProperty = Property retrieved from db.
};
}
}
And here is my test code.(I am using NUnit Test framework with Moq)
[Test]
public void TriggerCreateClicked()
{
var view = new Mock<IMockView>();
var viewModel = new Mock<IMockViewModel>();
var presenter = new MockPresenter(view.Object, viewModel.Object);
viewModel.Setup(x => x.IsValid).Returns(true)
.Raises(t => t.ButtonClickedEvent += null, EventArgs.Empty);
viewModel.Object.IsValid = true;
Assert.NotNull(presenter.MyProperty);
}
Basically, on my test case,
If ViewModel.IsValid returns true, I am raising the ButtonClickedEvent.
Then, inside of Presenter, I want to retrieve some property from db and store it in MyProperty. Then, I would like to test if this MyProperty is Not Null. If the test went through fine with no exception, presenter that has MyProperty should hold some values.
My question is, is it appropriate for me to create MockPresenter(not interface) that inherits RealPresenter(class) in order to perform Mock Test? Since my code in the RealPresenter does not provide any getters or setters to retrieve this Property, I decided to inherit RealPresenter by MockPresenter class in order not to impact on my RealPresenter. I have not seen any sample codes online that makes my approach feasible.
The first question is whether you are testing only one thing in your test method. In your case, I think you are testing two things in one method: raising event when validation returns true and retrieving data when event is handled. I suggest you separate them into two test methods.
The second question is you use Mock without verifying, which means all mocks in your test method is stubs. I guess in your method at least you will verify one.
The third question is I did not get what your real logic since you put some additional logic in your mock interface and test method.
I think in unit testing of WPF with MVVM, you might not have to test raising event handler since that is .Net framework's job. What you need test is event handler works correctly. If it through command binding you can mock the command to test the calling if command's implementation contains dependencies such database connection.
Related
I have developed an WPF application using MVVM as a architecture and am writing some unit tests as part of this. In my view I have a button that is bound to a property in the ViewModel which can be seen below.
ViewModel
public ICommand MoreInfoCommand
{
get
{
if (_moreInfoCommand == null)
{
_moreInfoCommand = new RelayCommand(parameter => OpenLink());
}
return _moreInfoCommand;
}
}
private void OpenLink()
{
try
{
Process.Start("https://www.google.com/");
}
catch
{
// catch error...
}
}
In my unit testing I have created the following unit test:
UnitTest
[Description("Test MoreInfoCommand")]
[TestMethod]
public void TestMoreInfoCommand()
{
viewModel vm = new viewModel();
Assert.IsTrue(vm.MoreInfoCommand.CanExecute(null));
}
Currently this tests the the property to see if when the button is clicked in the UI the relevant method can be executed. This passes as the conditions are met, however its my understanding I need to test the functionality as well. With this in mind how do I, for example tests that the correct functionality occurs when the button is clicked. I.e how to test what occurs when the ICommand MoreInfoCommand is executed as a result of button click in the UI.
I know private methods can be tested directly, but should in my unit testing I be checking the functionality as well and if so, how can I do this.
Thanks in advance.
Your view model isn't really testable. If you want to it to be, you should replace the call to the static Process.Start method with a call to a method of a interface that you inject the view model with:
public ViewModel(IProcessLoader processLoader) =>
_processLoader = processLoader;
//...
private void OpenLink()
{
try
{
_processLoader.Start("https://www.google.com/");
}
catch
{
// catch error...
}
}
You could then mock the interface in your unit test, for example using a mocking framwork like Moq:
[TestMethod]
public void TestMoreInfoCommand()
{
//Arrange
Mock<IProcessLoader> processLoader = new Mock<IProcessLoader>();
viewModel vm = new viewModel(processLoader.Object);
ICommand command = vm.MoreInfoCommand;
//Act
command.Execute(null);
//Assert
processLoader.Verify(x => x.Start(It.IsAny<string>()));
}
In the real app, you would implement the interface as a wrapper around Process.Start:
public interface IProcessLoader
{
void Start(string s);
}
public class ProcessLoader : IProcessLoader
{
public void Start(string s) => Process.Start(s);
}
It's important to realize that you should only verify that the method is called from the view model. A unit test against the view model class should not test the functionality of the Process class. The resposibility of the view model ends when Start has been called.
.NET and the underlying OS is responsible for what the Process class actually does. You should not test this but only your own code.
vm.MoreInfoCommand.CanExecute(null) would only call the canExecute method in your RelayCommand, but you did not provide any. CanExecute tells nothing about whether OpenLink would perform successfully or not.
Although I am no unit test specialist, if your code real looks like this, I doubt if it's worth to write a unit test for it in the first place, because it is so very simple.
As the comment from user auburg states, you can check, whether the process starts, although the process's name would depend on which browser was the standard browser. Also, you would have to wait for some time for the process to start. And maybe there was a process with the same name already running, lots of chances for trouble.
If you really want, you can check, if one of the well known mocking frameworks, e.g. Moq or Rhino Mocks, is able to mock away Process.Start.
Below is the piece of the code of my action :-
public ActionResult Edit(int id)
{
ProductViewModel viewmodel = GetProduct(id);
if (viewmodel != null)
{
....................
}
}
In above code the if condition is based on the viewmodel.Which is returning from the GetProduct() method.Where GetProduct() method is the private method of the controller.
And i want to mock the ProductViewModel in my unit test method with MOQ.Can anyone suggest me what is the best way to do that ?
Ideally your viewModel should only have public properties that your view will be bound to. So there should not be a scenario where you would need to mock the viewModel class.
If it is possible to, mock the GetProduct method to return an instance of ProductViewModel where the public properties have already been set. That way your viewModel will return exactly the values you want it to return for your test case.
Usually using the MVVM pattern will look like :
public class MainViewModel : MyViewModelBase
{
private readonly IDataService _dataService;
public MainViewModel(IDataService dataService)
{
_dataService = dataService;
// ...
}
//..
}
And you'll have a locator that looks like:
public class ViewModelLocator
{
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
}
else
{
SimpleIoc.Default.Register<IDataService, DataService>();
}
// Here you'll register your view models
SimpleIoc.Default.Register<MainViewModel>();
}
//..
}
So, mocking this is fairly easy, just use the DI to pass in whatever you want to pass, and hook your methods either to static data (usually done to have nice output in design mode), or dummy methods that will return whatever it is you need.
The correct approach is to test indirectly the GetProduct method. Based on the name you are getting info from some kind of storage and you can mock that storage and return an object which is mapped by GetProduct in the ViewModel you want. You shouldn't mock method of the same class you are testing.
Your controller is very strongly coupled with the business logic, in this case the GetProduct method. I would suggest to restructure your code to have an interface for your "Product" specific business logic. The product controller should depend on an abstraction i.e. the interface and not anything that is concrete.
Use any dependency injection framework like sring.net, MS unity etc to inject concrete implementations (dependencies) into your controller.
Now use MOQ to mock the business logic so that controller can be tested in isolation.
Lastly, this is just another wonderful example demonstrating how if it becomes difficult to unit test a particular code component, it more than often points towards a design flaw than a unit testing/mocking framework incapability.
I am new in unit testing.
public List<BookList> GetBookList(int bookid)
{
List<BookList> _BookList = new List<BookList>();
//Consider if some wcf call is there then how we can develop unit test
using (DataClassesDataContext context = new DataClassesDataContext(_strConnectionStringName))
{
foreach (tblBook_Sel_BasedOnbookIDResult _tblBook_selResult in context.tblBook_Sel_BasedOnBookID(bookid))
{
BookList _bookListObject = new BookList();
//Setting the proerty here
_BookList .Add(_bookListObject);
}
}
return _BookList;
}
I want to write unit test for this method.Please suggest which scenario of the above function i can test through unit testing and how .I can understand better if you can elaborate with some code example and how mocking can help us in above scenario.Thanks in advance.
You have a strong dependency to data access class, so probably you should inject it, if you have context as class member,initialized by injection from constructor, you easily can mock it from your unit test; the best approach is to have a contructor with IDataAccess parameter.
EDIT:
probably there is some problem to this snippet, but the idea is:
public interface IDataClassesDataContext
{
tblBook_Sel_BasedOnbookIDResult tblBook_Sel_BasedOnBookID(int bookid);
}
public partial class DataClassesDataContext:IDataClassesDataContext
{
}
public class Class1
{
IDataClassesDataContext _context;
public Class1(IDataClassesDataContext context)
{
_context = context;
}
public List<BookList> GetBookList(int bookid)
{
List<BookList> _BookList = new List<BookList>();
//Consider if some wcf call is there then how we can develop unit test
using (_context)
{
foreach (tblBook_Sel_BasedOnbookIDResult _tblBook_selResult in _context.tblBook_Sel_BasedOnBookID(bookid))
{
BookList _bookListObject = new BookList();
//Setting the proerty here
_BookList.Add(_bookListObject);
}
}
return _BookList;
}
}
This function is a stretched out two-liner, where one of the lines is data access. This function would be one I'd mock to unit test those that rely on it. You cannot unit test it, because it relies on outside data sources and therefore is not a single unit. If external sources are involved, you can use integration testing instead.
Some possible scenarios:
bookId parameter is negative, zero and positive. You can use int.MaxValue and int.MinValue.
_strConnectionStringName is null, empty, invalid and valid.
Tests for possible exceptions that can be thrown by tblBook_Sel_BasedOnBookID method.
Based on properties of the BookList class, you can have multiple test cases.
Please note that you should be calling a mock tblBook_Sel_BasedOnBookID method here. This method does not really care what goes on inside tblBook_Sel_BasedOnBookID. However, it looks a tad difficult are you are dealing with concrete type here.
For service, again a mock service call should made instead to making a real service call and based on conditions it can return a hard coded result or an exception.
I am trying to setup tests for my new projects and come across some difficulties.
I am using NUnit and Rhino Mocks.
The Code that I am trying to test is this,
public DocumentDto SaveDocument(DocumentDto documentDto)
{
Document document = null;
using (_documentRepository.DbContext.BeginTransaction())
{
try
{
if (documentDto.IsDirty)
{
if (documentDto.Id == 0)
{
document = CreateNewDocument(documentDto);
}
else if (documentDto.Id > 0)
{
document = ChangeExistingDocument(documentDto);
}
document = _documentRepository.SaveOrUpdate(document);
_documentRepository.DbContext.CommitChanges();
}
}
catch
{
_documentRepository.DbContext.RollbackTransaction();
throw;
}
}
return MapperFactory.GetDocumentDto(document);
}
And my testing code is as follows
[Test]
public void SaveDocumentsWithNewDocumentWillReturnTheSame()
{
//Arrange
IDocumentService documentService = new DocumentService(_ducumentMockRepository,
_identityOfSealMockRepository, _customsOfficeOfTransitMockRepository,
_accountMockRepository, _documentGuaranteeMockRepository,
_guaranteeMockRepository, _goodsPositionMockRepository);
var documentDto = new NctsDepartureNoDto();
documentDto.IsDirty = true;
documentDto.Id = 0;
//Act
var retDocumentDto = documentService.SaveDocument(documentDto);
//Assert
Assert.AreEqual(documentDto, documentDto);
}
private static IDbContext CreateMockDbContext()
{
var dbContext = MockRepository.GenerateMock<IDbContext>();
// setup expectations for DbContext mock
//dbContextMock.Expect(...)
// bind mock of the DbContext to property of repository.DbContext
_ducumentMockRepository.Expect(mock => mock.DbContext).Return(dbContext).Repeat.Any();
return dbContext;
}
I need to pass in a documentDto with say isDirty set and test if it returns the same object.
So I was thinking to use a Stub instead of a mock.
I need to to find out how to set expectations so I can test the logic on the code.
you need to mock or stub all of the components which you do not want to test. You should, as a rule of thumb only have a maximum of single mock object the rest should be stubs. Mock the things you want to verify interaction with and stub the things which you just want to provide data for your test.
you don't tell us what type your _documentRepository is so its hard to tell exactly what you are testing here, but to test this method the only thing you can do, IMHO, is check that if the IsDirty flag is set is check that the correct methods on the _documentRepository and the Context are called.
To do this I would create a mock _documentRepository and mock DbContext and set expectations that _documentRepository.SaveOrUpdate(document) is called with the document passed in. Actually looking again at the code you need to convert between the dto and the document. Currently this is being done in a method. I would create a interface and a class for this and make that interface a dependency of the class you are testing so that you can create a stub which returns a known document from the documentDto. This class could handle creating a new document or returning an existing one based on the id in the Dto. otherwise you'll have to know what type of document is returned.
something like:
var documentDto = new NctsDepartureNoDto();
documentDto.IsDirty = true;
documentDto.Id = 0;
IDbContext context = MockRepository.GenerateMock<IDbRepository>();
context.Expect(x=>x.BeginTransaction()).Return(MockRepository.GenerateStub<ITransaction>());
context.Expect(x=>x.CommitChanges());
then create a mock for the repository
IDocumentRepository repo = MockRepository.GenerateMock<IDocumentRepository>();
repo.Expect(x=>x.DbContext).Return(context).Repeat().Any();
repo.Expect(x=>x.SaveOrUpdate(Arg<Document>.Is.Any())).Return(MockRepository.GenerateStub<Document>);
This tests that you interact with the repository object correctly when the dirty flag is set. It shouldn't test that the document is saved correctly or that the correct document is returned when SaveOrUpdate is called, as this should be tested in the tests for the repository, not here.
'But wait!' I hear you cry, 'you said at the beginning that there should only be a single mock, and here we have 2!'. That's true, and I think that this shows a fault in your current design.
You should not, I don't think, be exposing the DBContext from your documentRepository. You seem to be doing so in order to use the transactions.
If your repository needs to be aware of the transactions then have methods on the repository that allow the transactions to be controlled (or hide the fact that the transactions exist inside the repository object completely). These methods might just delegate to the internal DbContext but it would then mean that the only mock would need to be the document repository object itself, and not the DbContext
I'm trying to implement unit tests in my current project. After that I'll start developing using TDD further on in this project.
Yesterday I started making some tests and it wasn't as easy as it looks in theory/books.
At the moment I'm struggling with a specific scenario, which I know someone else must have worked with in the past also.
Some background information.
I've got a method called Add() in the class AddProduct. When a new object is passed to the Add method, there has to be made a new Item first, so I'll have to call the Add() method of the AddItem class first.
All of this code exists in the Business Layer. Off-course the real adding happens in the DAL, which is called from within my AddProduct and AddItem classes.
To get an idea, this is what I have so far:
public class AddProduct : Product<IDataAccessAdd<Entities.Product>>, IBusinessAdd<Entities.Product>
{
private readonly Business.IBusinessAdd<Entities.Item> _addItem;
public AddProduct() : base(new DataAccess.AddProduct())
{
_addItem = new AddItem();
}
public AddProduct(DataAccess.IDataAccessAdd<Entities.Product> dal, Business.IBusinessAdd<Entities.Item> itemBl) : base(dal)
{
_addItem = itemBl;
}
private Entities.Product _newProduct;
public bool Add(ref Product product, string user)
{
bool isAdded = false;
_newProduct = product;
if(AddNewItem(user))
{
isAdded = Dal.Add(product);
}
return isAdded;
}
private bool AddNewItem(string user)
{
var newItem = new Item();
bool isAdded = _addItem.Add(ref newItem, user);
_newProduct.Item = newItem;
return isAdded;
}
}
As you can see, I'm calling the AddNewItem from within the Add method.
The problem in this example is the constructor.
I'd like to have a constructor with 0 or 1 parameter, like so:
public AddProduct() : base(new DataAccess.AddProduct())
{
}
public AddProduct(DataAccess.IDataAccessAdd<Entities.Product> dal) : base(dal)
{
}
and the AddNewItem method like so (or something similar):
private bool AddNewItem(string user)
{
var newItem = new Item();
var addItem = new Business.AddItem();
bool isAdded = addItem.Add(ref newItem, user);
_newProduct.Item = newItem;
return isAdded;
}
But when doing this, the code executed in the AddNewItem method uses a 'real' DAL and I don't want that in a unit test. I solved this issue by adding a new parameter to the constructor, which can also create a mock DAL for the Business.Item class. However, I don't think this is the way to go.
In theory, you could get a constructor with 20 parameters, all used for unit testing. Not a very pretty sight.
A colleague of mine told me this could probably be solved using a Factory Method design pattern, but he wasn't sure that would be a best choice.
As I've never worked with the Factory Method design pattern, I don't feel very comfortable implementing it when unit testing is new to me also.
Any other suggestions which I could try?
There's two approaches you can use here.
Setup a IOC container specifically for testing. In this container you would configure the dal service to be your test or mock DAL service.
Wire-up your classes manually. In this case you would explicitly call the AddProduct constructor and pass in your test or mock DAL service.
The rationale behind this is that dependency injection allows you to create a sandbox to isolate and test a specific part of your code. The options above create that sandbox.