Unit testing my Presenter that creates a Model in its constructor - c#

I am trying to unit test my WinForms application with MVP Passive View implemented. I have created Mock Views and Mock Models so that I can test my Presenters with some data I have set. However, I have run into a problem.
In the constructor of my Presenter, I create my Model. I have thought about eliminating this practice by implementing the Factory Pattern to create my Model without the Presenter knowing anything about the concrete implementation of the Model.
In my unit test, I am trying to test a method from my Presenter(InitializeAssessments) that uses its Model. I want to Presenter to use the Mocked Model there so that there is no connection to a database required and the Presenter just gets the data I set in the Mocked Model. However, since the Presenter creates the 'real' Model, the data is different and my test fails.
Do you think I should implement the Factory Pattern or is there a simple way to fix my issue in the unit testing itsself? Will the Factory Pattern solve my issue?
EDIT: For now I am thinking about creating the Model when I construct the Presenter in the View with homeScreenPresenter = new HomeScreenPresenter(this, new HomeScreenModel()); . So that I only have to reference the IModel in the Presenter itsself, making it easier to test.
Presenter constructor
public HomeScreenPresenter(IHomeScreenView view)
{
_model = new AssessmentsModel();
_view = view;
_view.InitializingAssessments += InitializeAssessments;
_view.CreatingNewAssessment += CreateNewAssessment;
_view.AddingNewStandard += AddNewStandard;
_view.OpeningAssessment += OpenAssessment;
}
Testclass
[TestClass()]
public class HomeScreenPresenterTests
{
MockHomeScreenView view;
MockAssessmentsModel model;
HomeScreenPresenter presenter;
[TestInitialize()]
public void TestInitialize()
{
view = new MockHomeScreenView();
model = new MockAssessmentsModel();
presenter = new HomeScreenPresenter(view);
}
[TestMethod()]
public void HomeScreenPresenterTest()
{
Assert.AreEqual(typeof(MockHomeScreenView), view.GetType());
Assert.AreEqual(typeof(MockAssessmentsModel), model.GetType());
Assert.AreEqual(typeof(HomeScreenPresenter), presenter.GetType());
}
[TestMethod()]
public void InitializeAssessmentsTest()
{
model.TestList = new List<string>
{
"assessment1",
"assessment1",
"assessment2"
};
var expectedList = new List<string>
{
"assessment1",
"assessment2"
};
presenter.InitializeAssessments(this, EventArgs.Empty);
Assert.AreEqual(expectedList, view.ExistingAssessments);
}

Related

Start a MVP WinForms application with Ninject

I am trying to startup an simple Model View Presenter WinForms application and use the constructor injection to inject IMainView, IEventPublisher and IRepository to the main presenter.
However, I am having some problems to find out how to exactly do this. My problem is that for some reason presenter seems to create two instances of the view or view is created and not shown.
Program.cs
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
//var view = kernel.Get<View.MainForm>();
var presenter = kernel.Get<Presenter>();
//Application.Run(view);
Application.Run();
If view is initialized on the program.cs, then also presenter creates its own view? And with the active approach above, the view is created but not shown.
Presenter.cs
public Presenter(IMainForm view,
IRepository repository,
IEventPublisher eventPublisher)
{
_view = view;
_repository = repository;
_reactiveEventPublisher = eventPublisher;
}
MainForm.cs
public Form(IEventPublisher eventPublisher)
{
_reactiveEventPublisher = eventPublisher;
}
NinjectBindings.cs
public class NinjectBindings : NinjectModule
{
public override void Load()
{
Bind<IRepository>().To<Repository>();
Bind<IMainForm>().To<View.MainForm>();
Bind<IEventPublisher>().To<ReactiveEventAggregator>().InSingletonScope();
Bind<Presenter>().ToSelf();
}
}
Question is, what is the proper way to start WinForms application in case the view is injected to the presenter?
Using Ninject 3.3.4 as IoC container.
If view is initialized on the program.cs, then also presenter creates
its own view?
This is because of the object scoping. If you request an IMainForm in Program.cs, and then request a Presenter, then Ninject will inject a new instance of View.MainForm for the Presenter and thus you have two instances of the view. To use the same instance you need to scope the binding in singleton scope.
Bind<IMainForm>().To<View.MainForm>().InSingletonScope();
When requesting an instance of the view, ensure you do so via your binding, i.e. var view = kernel.Get<View.IMainForm>(); otherwise Ninject will try to self-bind and will be dodging your singleton scope.

MVVM Light inject DataService with parameter

My ExampleViewModel has a parameter (a model) that it needs to function properly. I also have a list variant of the ExampleViewModel that just contains a ObservableCollection<ExampleViewModel> and has some wrapper methods.
The issue shows it self when I try to use dependency injection with MVVM Light. Let me explain the scenario with some code.
default ViewModelLocator:
public class ViewModelLocator {
public ViewModelLocator() {
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic) {
SimpleIoc.Default.Register<IDataService, DesignDataService>();
} else {
SimpleIoc.Default.Register<IDataService, DataService>();
}
SimpleIoc.Default.Register<MainViewModel>();
}
public MainViewModel Main {
get {
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
public static void Cleanup() {}
}
Simple MainViewModel:
public class MainViewModel : ViewModelBase {
private IDataService _service;
private MainModel _model;
// Goal. I think?
public MainViewModel(IDataService service, MainModel model) {
_service = service;
_model = model;
}
// Used now
public MainViewModel(MainModel model) {
_service = ServiceLocator.Current.GetInstance<IDataService>();
_model = model;
}
}
And the ListMainViewModel fills it's list like this:
Mains = new ObservableCollection<MainViewModel>(
_service.GetAll().Select(model => new MainViewModel(model))
);
Because of the list creation in the ListMainViewModel I can't inject the data source in the constructor and have to use it as shown under // Used now. Which is fine, but when I try to unit test problems occur, as you can probably imagine.
I use a unit test like this at the moment:
public void ListMainViewModel_DoSomething_Success() {
// Arrange
var mock = new Mock<IDataService>();
mock.Setup(m => m.Create(new MainModel { Naam = "Create" }));
mock.Setup(m => m.Update(new MainModel { Naam = "Update" }));
var listMainViewModel = new ListMainViewModel(mock.Object);
var selected = new MainModel() { Prop = "Test" };
listMainViewModel.SelectedMainViewModel = new MainViewModel(selected);
// Act
listMainViewModel.DoSomething();
// Assert
mock.Verify(x => listMainViewModel.DoSomething(), Times.Exactly(1));
}
Note: Not sure if the unit test is correct. But the problem occurs while creating the SelectedMainViewModel because it doesn't fetch a DataService.
For now I have two choices (I think), I can make the MainModel in MainViewModel optional, which is not something that should be possible and contructor inject the IDataService. Or I can discover a way to make the _service find-able by the MainViewModel.
Is there any elegant way to solve this? Because I have the feeling I have to make some hack using if (InDesignMode) or something similar.
You mention that:
I can't inject the data source in the constructor and have to use it as shown under // Used now.
What are you seeing when you try this? What exception is thrown? Why doesn't the below work?
Mains = new ObservableCollection<MainViewModel>(
_service.GetAll().Select(model => new MainViewModel(model, _service))
);
I think it may help if you get away from using a service locator, which looks to be an anti-pattern for your goal. When using a DI container, it's best to create the entire object graph at the application start or web request (for web apps). But here you are using the new keyword to create your MainViewModel.
See this post.

How do i mock a Interface with Moq or NInject Mocking Kernel

I just waded through questions and blogs on the subject of mocking and Dependency Injection. Come to a conclusion i just need to mock the interface that is consumed by client. I am looking forward to testing a simple use case here with no idea.
The Contract
public Interface IApplicationService
{
bool DeleteApplication(int id);
ApplicationDto AddApplication(ApplicationDto application);
IEnumerable<ApplicationDto> GetApplications();
}
Implementation ( I am going to mock )
public Class ApplicationService:IApplicationService
{
private EntityFrameworkRepo repo;
public ApplicationService()
{
repo = new EntityFrameworkRepo();
}
public ApplicationDto Add(ApplicationDto dto)
{
//add to dbcontext and commit
}
}
Mocking Code
[Test(Description = "Test If can successfully add application")]
public void CanAddApplication()
{
//create a mock application service
var applicationService = new Mock<IApplicationService>();
//create a mock Application Service to be used by business logic
var applicationDto = new Mock<ApplicationDto>();
//How do i set this up
applicationService.Setup(x => x.GetApplications()).Returns(IEnumerable<applicationDto.Object>);
}
And i for one am sure i need to test the business logic rather than mocking it. So what is it exactly i have to do to test my ApplicationService but then keep the entity framework out.
btw to speak of ApplicationService, it uses constructor injection with NInject. So mocking this with NInject.MockingKernel will setup dependency chain?
There is little or no benefit using dependency injection (IOC) container in unit testing. Dependency injection helps you in creating loose coupled components, and loose coupled components are easier to test, thats it.
So if you want to test some service, just create mockups of it dependencies and pass them to that service as usual (no need to involve IOC container here, I hardly can imagine, that you will need some features of IOC containers - like contextual binding, interception etc. - inside unit test).
If you want your ApplicationService to be easy to test, it should look more like:
public class ApplicationService: IApplicationService
{
private readonly IEntityFrameworkRepo repo;
// dependency passed by constructor
public ApplicationService(IEntityFrameworkRepo repo)
{
this.repo = repo;
}
// save to db when DTO is eligible
public ApplicationDto Add(ApplicationDto dto)
{
// some business rule
if(dto.Id > 0 && dto.Name.Contains(string.Empty)){
//add to dbcontext and commit
}else{
throw new NotEligibleException();
}
}
}
Here the dependency is passed by constructor. In your application code you will use it together with an IOC container to make constructor injection (IOC container will be responsible for creating instances of IEntityFrameworkRepo).
But in unit test, you can just pass instance of some implementation of IEntityFrameworkRepo created on your own.
ApplicationDto
As long as ApplicationDto is some object that can by created by hand, I can directly use it in unit-test (creating instances by hand). Otherwise I will have to wrap it by interface like IApplicationDto, in order to be able to mock it up with Moq.
public class ApplicationDto{
public int Id {get; set;}
public string Name {get; set;}
}
Here is how could unit-test look like:
In unit test I will use mocked implementaion of IApplicationRepo, because I do not want to configure e.g. database connections, web services etc. and my primary intention is to test the ApplicationService not the underlying repository. Another advantage is that the test will be runnable without specific configuration for various machines. To mockup some db repository I can use e.g. List.
[Test(Description = "Test If can successfully add application")]
public void CanAddApplicationIfEligible()
{
var repo = GetRepo();
var appService = new ApplicationService(repo);
var testAppDto = new ApplicationDto() { Id = 155, Name = "My Name" };
var currentItems = repo.ApplicationDtos.Count();
appService.Add(testAppDto);
Assert.AreEqual(currentItems + 1, repo.ApplicationDtos.Count());
var justAdded = repo.ApplicationsDto.Where(x=> x.Id = 155).FirstOrDefault();
Assert.IsNotNull(justAdded);
///....
}
private static IEntityFrameworkRepo GetRepo{
// create a mock repository
var listRepo = new List<ApplicationDto>{
new ApplicationDto {Id=1, Name="MyName"}
};
var repo = new Mock<IEntityFrameworkRepo>();
// setup the methods you know you will need for testing
// returns initialzed list instead of DB queryable like in real impl.
repo.Setup(x => x.ApplicationDtos)
.Returns<IQueryable<ApplicationDto>>(x=> listRepo);
// adds an instance of ApplicationDto to list
repo.Setup(x => x.Add(It.IsAny<ApplicationDto>())
.Callback<ApplicationDto>(a=> listRepo.Add(a));
return repo.Object;
}
Note:
There have been realeased an ninject.mockingkernel extension. The approach described in example on wiki can make your unit-test code bit tidier, but the approach described there is definetly not depencdency injection (it is service locator).

MVP view/presenter registration

I'm working on an MVP based GUI architecture for a WinForms application and would like to use Autofac to keep track of the different parts. I keep running into circular component dependencies and would appreciate a gentle push in the right direction.
The architecture is based on this post where the View is as passive as i gets. The View holds no reference to the Presenter. The View is passed to the Presenter on construction. So in the non-DI world you would start your program with:
var MainView = new MainView();
var mainPresenter = new MainPresenter(mainView, new DataRepository());
Application.Run(mainView);
Ok, so the Presenter needs to know about the View instance to do its job. How can I express that in the registration code? This is what I've tried:
builder.RegisterType<MainPresenter>().PropertiesAutowired().SingleInstance();
builder.RegisterType<MainView>().As<IMainView>().PropertiesAutowired().SingleInstance();
And then in Program.cs:
var mainPresenter = Container.Resolve<MainPresenter>();
Application.Run(Container.Resolve<IMainView>() as MainView);
But this way I need to remember to create the Presenter instance. However I would like to express in the registration that if I request a IMainView instance the MainPresenter should be kicked into action. But how....
Any hints, mockery or derisive laughter are welcome
I think you should be able to solve it this way: Register the presenter and view without property injection since you say the view needs no reference to the presenter, and constructor injection is considered best practice in Autofac:
builder.RegisterType<MainPresenter>().SingleInstance();
builder.RegisterType<MainView>().As<IMainView>();
Inject the view into the presenter through constructor and publish it as a readonly property:
public class MainPresenter
{
// Private variables
private readonly IMainView _view;
// Constructor
public MainPresenter(IMainView view)
{
_view = view;
}
// Properties
public IMainView View
{
get { return _view; }
}
}
Then you fire up the application through a single resolve:
var mainPresenter = Container.Resolve<MainPresenter>();
Application.Run(mainPresenter.View as Form);
Finally, if you find later on that you need a reference from the view to the presenter, I think you would have to use property-injection on the view to avoid circular reference exceptions. Then you can register the view like this:
builder.RegisterType<MainView>().As<IMainView>().PropertiesAutowired(PropertyWiringFlags.AllowCircularDependencies);
and supply the view with a read/write property that will be set by Autofac
public MainPresenter Presenter { get; set; }

windows form & design pattern

i am familier with mvc,mvp or mvvm patter. so i was searching google for implementing good design patter for win form apps. i found lots of article.few guys said mvc is good and few guys said mvp is perfect for win apps. i found a very small code which implement mvp in win apps. i go through the code and found that developer has to write lot of extra code to bind treeview or any control.
the code as follows
public interface IYourView
{
void BindTree(Model model);
}
public class YourView : System.Windows.Forms, IYourView
{
private Presenter presenter;
public YourView()
{
presenter = new YourPresenter(this);
}
public override OnLoad()
{
presenter.OnLoad();
}
public void BindTree(Model model)
{
// Binding logic goes here....
}
}
public class YourPresenter
{
private IYourView view;
public YourPresenter(IYourView view)
{
this.view = view;
}
public void OnLoad()
{
// Get data from service.... or whatever soruce
Model model = service.GetData(...);
view.BindTree(model);
}
}
please someone go through the code and help me to understand the flow because how code should be written in mvp patter that i dont know. thanks.
This code is already using the MVP pattern.
It declares an interface IYourView and a concrete class YourView that implements System.Windows.Form and this new interface. Essentially what that is doing is creating a new form with the added requirement that it also implements the BindTree() method defined in IYourView.
The YourView class (form) then has a dependency of YourPresenter in order to hook up the OnLoad event with the presenter, although I'd do it where the presenter subscribes to the form's OnLoad event instead.
The presenter YourPresenter takes as a dependency an instance of YourView and it can then use that instance in the rest of its logic.
Now, to use that you would follow a process similar to this:
Create a new instance of YourView (which then in turn creates the presenter)
Implement logic in the presenter (ie- create GetModel()) to create the Model that you want to bind to the tree
Call view.BindTree(model) in the presenter where model is what you just created in the previous step
So, create an instance of your view:
IYourView newView = new YourView();
Then in your presenter class:
Model model = GetModel();
newView.BindTree(model);

Categories

Resources