Testing a ViewModel in WPF MVVM with Moq framework - c#

I am new to Moq framework. I have a viewmodel with injected IEntityRepository
public class MainViewModel
{
private readonly IEntityRepository _entityRepository;
public MainViewModel(IEntityRepository entityRepository)
{
_entityRepository = entityRepository;
Entities = new ObservableCollection<EntityWrapper>();
}
public ObservableCollection<EntityWrapper> Entities { get; set; }
public void Load()
{
var entities = _entityRepository.GetAll();
Entities.Clear();
foreach (var entity in entities)
{
Entities.Add(new EntityWrapper(entity));
}
}
public void AddEntity(string name, int x, int y)
{
var entity = new Entity()
{
Name = name,
X = x,
Y = y
};
_entityRepository.AddEntity(entity);
_entityRepository.Save();
}
}
and EntityRepository is like this:
public class EntityRepository : IEntityRepository
{
private Context _context;
public EntityRepository(Context context)
{
_context = context;
}
public Entity Get(long id)
{
return _context.Entities.Find(id);
}
public IEnumerable<Entity> GetAll()
{
return _context.Entities.ToList();
}
public void AddEntity(Entity entity)
{
_context.Entities.Add(entity);
}
public void Save()
{
_context.SaveChanges();
}
}
Now, I want to test Load and AddEntity methods of MainViewModel
this is my test class:
[TestClass]
public class MainViewModelTests
{
private Mock<IEntityRepository> _mockRepo;
private MainViewModel _mainViewModel;
public MainViewModelTests()
{
_mockRepo = new Mock<IEntityRepository>();
_mainViewModel = new MainViewModel(_mockRepo.Object);
}
[TestMethod]
public void AddEntityTest()
{
var entity = new Entity()
{
Name = "Student",
X = 10,
Y = 20
};
_mainViewModel.AddEntity("Student", 10, 20);
_mockRepo.Setup(m => m.AddEntity(entity));
_mockRepo.Setup(m => m.Save());
var entities = _mainViewModel.Entities;
Assert.AreEqual(1, entities.Count);
}
[TestMethod]
public void LoadTest()
{
// How to add fake data???
_mockRepo.Setup(r => r.GetAll());
_mainViewModel.Load();
var entities = _mainViewModel.Entities;
Assert.AreEqual(1, entities.Count);
}
}
In AddEntityTest() I don't know why the property Entities will be empty and in LoadTest how to populate fake data so that I can load it.

To get a test data in LoadTest method you can use Moq Returns method
_mockRepo.Setup(r => r.GetAll()).Returns(new List<Entity> { new Entity() });
It works, because List<T> implements IEnumerable<T>.
As for the AddEntityTest, there are a couple of issues here. You setup the mock
_mockRepo.Setup(m => m.AddEntity(entity));
_mockRepo.Setup(m => m.Save());
after _mainViewModel.AddEntity("Student", 10, 20); call. It should come before, Arrange step is always before Act step, according to AAA pattern
You also don't update Entities collection after adding an entity, so the Entities.Count remains the same. I suggest you to setup a IEntityRepository.GetAll() mock as well for this test and update an Entities collection in MainViewModel. Or rewrite the logic of your AddEntityTest, if collection update performed through view

Related

Mocking a repository that uses EF using Moq, preserving behavior of ContextTracker

So I have a generic repository like this:
using System.Collections.Generic;
using System.Data.Entity;
using System.Threading.Tasks;
namespace TrackIt.UI.Data.Repositories
{
public class GenericRepository<TEntity, TContext> : IGenericRepository<TEntity>
where TContext: DbContext
where TEntity: class
{
protected readonly TContext Context;
protected GenericRepository(TContext context)
{
this.Context = context;
}
public virtual async Task<TEntity> GetByIdAsync(int id)
{
return await Context.Set<TEntity>().FindAsync(id);
}
public bool HasChanges()
{
return Context.ChangeTracker.HasChanges();
}
}
}
And a FriendRepository that inherits from it, with some of its own methods:
using System.Data.Entity;
using System.Threading.Tasks;
using TrackIt.DataAccess;
using TrackIt.Model;
namespace TrackIt.UI.Data.Repositories
{
public class FriendRepository : GenericRepository<Friend, TrackItDbContext>,
IFriendRepository
{
public FriendRepository(TrackItDbContext context): base(context)
{
}
public override async Task<Friend> GetByIdAsync(int id)
{
return await Context.Friends.Include(f => f.PhoneNumbers).SingleAsync(f => f.Id == id);
}
}
}
where TrackItDbContext is just a class inheriting from DbContext, where it has properties that "maps" to the database's tables.
Then, I have an implementing class like this:
namespace TrackIt.UI.ViewModel
{
public class FriendDetailViewModel : DetailViewModelBase, IFriendDetailViewModel
{
public bool HasChanges
{
get { return _hasChanges; }
set
{
if(_hasChanges != value)
{
_hasChanges = value;
OnPropertyChanged();
((DelegateCommand)SaveCommand).RaiseCanExecuteChanged();
}
}
}
private Friend _friend;
public Friend Friend
{
get { return _friend; }
private set
{
_friend = value;
OnPropertyChanged();
}
}
private ICommand _addPhoneNumberCommand;
public ICommand AddPhoneNumberCommand
{
get { return _addPhoneNumberCommand; }
set { _addPhoneNumberCommand = value; }
}
public ObservableCollection<FriendPhoneNumberDecorator> PhoneNumbers { get; }
private IFriendRepository _friendRepository;
private IMessageDialogService _messageDialogServiceProvider;
public FriendDetailViewModel(IFriendRepository friendRepository,
IEventAggregator eventAggregator,
IMessageDialogService messageDialogServiceProvider) : base(eventAggregator)
{
_friendRepository = friendRepository;
_messageDialogServiceProvider = messageDialogServiceProvider;
PhoneNumbers = new ObservableCollection<FriendPhoneNumberDecorator>();
AddPhoneNumberCommand = new DelegateCommand(OnAddPhoneNumberExecute);
DeletePhoneNumberCommand = new DelegateCommand(OnDeletePhoneNumberExecute, OnDeletePhoneNumberCanExecute);
}
private void FriendPhoneNumberWrapper_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
// Ensures that the HasChanges property of the viewmodel is updated
if (!HasChanges)
{
HasChanges = _friendRepository.HasChanges();
}
// If the change in phone number causes validation errors, disable the save button
if (e.PropertyName == nameof(FriendPhoneNumberDecorator.HasErrors))
{
((DelegateCommand)SaveCommand).RaiseCanExecuteChanged();
}
}
private void OnAddPhoneNumberExecute()
{
var newNumber = new FriendPhoneNumber();
newNumber.PropertyChanged += FriendPhoneNumberWrapper_PropertyChanged;
PhoneNumbers.Add(newNumber);
Friend.PhoneNumbers.Add(newNumber);
newNumber.Number = "";
}
#endregion
}
}
When using this class, an instance of IFriendRepository is injected by a DI container and assigned to _friendRepository. The line Friend.Model.PhoneNumbers.Add in the OnAddPhoneNumberExecute method adds a PhoneNumber instance (newNumber) to Friend.PhoneNumber. This addition is tracked by Context in HasChanges method in the GenericRepository method (I checked this by debugging), and thus when the _friendRepository.HasChanges() method in FriendPhoneNumberWrapper_PropertyChanged event handler is triggered by the newNumber.Number = "" line, it returns true.
But, when I test if the HasChanges property of the class is updated when I raise the command AddPhoneNumberCommand using the following test:
namespace TrackIt.UITests.ViewModel
{
public class FriendDetailViewModelTests
{
private FriendDetailViewModel _viewModel;
private Mock<IEventAggregator> _eventAggregatorMock;
private Mock<IMessageDialogService> _messageDialogServiceMock;
private Mock<IFriendRepository> _friendRepositoryMock;
private readonly Friend testFriend = new Friend
{
Id = 2,
FirstName = "asdf",
LastName = "asdfasdf",
Email = "test#test.com",
FavoriteLanguage = new ProgrammingLanguage { Id = 1, Name = "C++"},
PhoneNumbers = new List<FriendPhoneNumber> {
new FriendPhoneNumber(){ id = 1, Number = "0123" },
new FriendPhoneNumber(){ id = 2, Number = "4567" },
}
};
public FriendDetailViewModelTests()
{
// Set up dependencies for FriendDetailViewModel class.
_messageDialogServiceMock = new Mock<IMessageDialogService>();
_eventAggregatorMock = new Mock<IEventAggregator>();
_friendRepositoryMock = new Mock<IFriendRepository>();
// Mock the friendrepository getbyidasync method
_friendRepositoryMock.Setup(dp => dp.GetByIdAsync(testFriend.Id)).ReturnsAsync(testFriend);
// Finally, create the FriendDetailViewModel!
_viewModel = new FriendDetailViewModel(_friendRepositoryMock.Object, _eventAggregatorMock.Object, _messageDialogServiceMock.Object);
}
[Fact]
public void ShouldAddNewPhoneNumberEvent()
{
// ARRANGE
// Assign testFriend to Friend (required so that the created phone number can be assigned to an instance, otherwise we get null reference exception)
PrivateObject _viewModelPrivated = new PrivateObject(_viewModel);
_viewModelPrivated.SetProperty(nameof(Friend), testFriend);
// Create a test empty phone number, to be compared later against the phone number created when user presses "Add"
var emptyPhoneNumber = new FriendPhoneNumber();
emptyPhoneNumber.Number = "";
// ACT
_viewModel.AddPhoneNumberCommand.Execute(null);
// ASSERT
// Check if the created phone number is an empty phone number, the dbContext sees there's a change,
// and that the save button can be pressed
Xunit.Assert.Contains(emptyPhoneNumber, _viewModel.PhoneNumbers,
new ByPropertyComparer<FriendPhoneNumberDecorator>(nameof(emptyPhoneNumber.Number)));
Xunit.Assert.True(_viewModel.HasChanges);
Xunit.Assert.True(_viewModel.SaveCommand.CanExecute(null));
}
}
}
the test fails at Xunit.Assert.True(_viewModel.HasChanges); line, which means the _friendRepository.HasChanges() is not updating automatically (i.e. not tracking) when the Friend.Model.PhoneNumbers.Add is called. I realize that this would be due to me mocking the IFriendRepository, and so it may not actually be tracking any changes. Am I right? Should I also mock HasChanges() of _friendRepositoryMock ? Or is there a better way to do this, maybe an in-memory database? But then it would not be a unit test?

NSubstitute and DbContext.Set<TEntity> Could not find a call to return from

I am trying to write some tests for an existing service we have. It uses the DbContext (In our case, named DatabaseContext) and the constructor looks like this:
public GenericOrderProvider(DatabaseContext context, IOrderHandler<T> orderHandler)
{
_orderHandler = orderHandler;
_context = context;
_dbSet = context.Set<T>();
}
As you can see, it's generic and sets the _dbSet when it's initialized.
I have this very simple method:
public Attempt<IQueryable<T>> List(params string[] includes)
{
var x = _dbSet.ToList();
return Attempt<IQueryable<T>>.Succeed(_dbSet.OrderBy(m => m.Order));
}
And I wrote this test:
[TestFixture]
public class ListShould
{
[Test]
public void ReturnList()
{
// Assemble
var services = GenericOrderProviderContext.GivenServices();
var provider = services.WhenCreateOrderProvider();
services.DatabaseContext.Set<Attribute>().ReturnsForAnyArgs(new List<Attribute>().ToDbSet());
//services.DatabaseContext.Attributes = new List<Attribute>().ToDbSet();
// Act
var result = provider.List();
// Assert
result.Failure.Should().BeFalse();
result.Result.Count().Should().Be(0);
}
}
When I run that test, I get the error:
NSubstitute.Exceptions.CouldNotSetReturnDueToNoLastCallException : Could not find a call to return from.
The trace specifically targets the line services.DatabaseContext.Set<Attribute>().ReturnsForAnyArgs(new List<Attribute>().ToDbSet()); but I have no idea how to fix it.
As far as I can tell, I am mapping to the right method.
For completeness, here is my test Contexts:
public class GenericOrderProviderContext: DatabaseContextContext<GenericOrderProviderContext>
{
public static GenericOrderProviderContext GivenServices() => new GenericOrderProviderContext();
public IGenericOrderProvider<Attribute> WhenCreateOrderProvider() =>
new GenericOrderProvider<Attribute>(DatabaseContext,
new OrderHandler<Attribute>(DatabaseContext));
public bool IsSequential(List<Attribute> models)
{
return !models.OrderBy(m => m.Order).Select(m => m.Order).Select((i, j) => i - j).Distinct().Skip(1).Any();
}
}
public class DatabaseContextContext<T> where T: DatabaseContextContext<T>
{
public DatabaseContext DatabaseContext;
protected DatabaseContextContext()
{
DatabaseContext = Substitute.For<DatabaseContext>();
}
}
Does anyone know what I can do to resolve this issue?

Mock Generic Repository with contexts

I have a generic repository for several contexts. I can extend it and use it for services without problem. However, When I mock it, this.Entities in the constructor is always null.
GenericDataRepsository
public class GenericDataRepository<T, C> : IGenericDataRepository<T, C> where T : class where C : DbContext, new() {
protected C context;
protected IDbSet<T> Entities;
public GenericDataRepository() {
this.context = new C();
this.Entities = context.Set<T>();
}
public GenericDataRepository(C context) {
this.context = context;
this.Entities = context.Set<T>(); // Problem is here. Entities didn't get set when mocking
}
public virtual IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate) {
return Entities.Where(predicate).ToList();
}
// omitted Add, Update, Delte
}
Unit Test
[Test]
public void GetBIlloTo() {
var data = new List<BillTo> {
new BillTo { CONTACTID = 12, COUNTRY = "USA" }
}.AsQueryable();
var mockSet = Substitute.For<DbSet<BillTo>, IQueryable<BillTo>>();
((IQueryable<BillTo>)mockSet).Provider.Returns(data.Provider);
((IQueryable<BillTo>)mockSet).Expression.Returns(data.Expression);
((IQueryable<BillTo>)mockSet).ElementType.Returns(data.ElementType);
((IQueryable<BillTo>)mockSet).GetEnumerator().Returns(data.GetEnumerator());
var mockContext = Substitute.For<MyEntities>();
mockContext.BillToes.Returns(mockSet);
var repo = new GenericDataRepository<BillTo, MyEntities>(mockContext);
//// Act
var actual = repo.FindBy(r => r.CONTACTID == 12);
//// Assert
Assert.AreEqual(actual.Count(), 1);
}
MyEntities - generated by EF and I didn't change it.
public partial class MyEntities : DbContext
{
public MyEntities()
: base("name=MyEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<BillTo> BillToes { get; set; }
}
I'm using EF database first, NUnit, and Nsubstitute. Tried Moq as well, same problem. So, Why didn't Entities get set?
You didn't set your mock object to return any value using the method set<T>.
Just add the following call before you initialize your class under test:
mockContext.Set<BillTo>().Returns(mockSet);
Why have a FindBy method at all? Why not have a FindAll() that returns the the this.Entities = context.Set() something like
public IQueryable<T> FindAll()
{
return _context.Set<T>());
}
Then the user of the repository can tack on any linq predicate they want
and you can mock or fake the FindAll() method to return whatever list of entities you want.

How to mock IRepository<T>?

I want to mock a unit of work interface with repositories inside for unit test purpose. So far I am able to do it like below.
namespace Liquid.Service.UnitTest
{
using Liquid.DataAccess.Interface;
using Liquid.Domain;
using Domain.Interface;
using Moq;
using System.Collections.Generic;
using System.Linq;
internal class Helper
{
internal Mock<IUnitOfWork> MockUnitOfWork(ICollection<Dummy> dummies = null,
ICollection<ProductType> productTypes = null)
{
dummies = dummies ?? new List<Dummy>();
productTypes = productTypes ?? new List<ProductType>();
var dummyRepositoryMock = MockDummyRepository(dummies);
var productTypeRepositoryMock = MockProductTypeRepository(productTypes);
var unitOfWorkMock = new Mock<IUnitOfWork>();
unitOfWorkMock.Setup(x => x.DummyRepository)
.Returns(dummyRepositoryMock.Object);
unitOfWorkMock.Setup(x => x.ProductTypeRepository)
.Returns(productTypeRepositoryMock.Object);
return unitOfWorkMock;
}
private Mock<IDummyRepository> MockDummyRepository(ICollection<Dummy> dummies)
{
var dummyRepositoryMock = new Mock<IDummyRepository>();
dummyRepositoryMock.Setup(x => x.FindById(It.IsAny<int>()))
.Returns((int arg1) => dummies.Where(x => x.Id == arg1).SingleOrDefault());
dummyRepositoryMock.Setup(x => x.Add(It.IsAny<Dummy>()))
.Callback((Dummy arg1) => dummies.Add(arg1));
return dummyRepositoryMock;
}
private Mock<IProductTypeRepository> MockProductTypeRepository(ICollection<ProductType> productTypes)
{
var productTypeRepositoryMock = new Mock<IProductTypeRepository>();
productTypeRepositoryMock.Setup(x => x.FindById(It.IsAny<int>()))
.Returns((int arg1) => productTypes.SingleOrDefault(x => x.Id == arg1));
productTypeRepositoryMock.Setup(x => x.Add(It.IsAny<ProductType>()))
.Callback((ProductType arg1) => productTypes.Add(arg1));
return productTypeRepositoryMock;
}
}
}
You see that I've created two method to mock DummyRepository and ProductTypeRepository but because it has same implementation, I think it is redundant for every repositories I have.
Below is the Repositories and IRepository code.
namespace Liquid.DataAccess.Interface
{
using Liquid.Domain;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
public interface IDummyRepository : IRepository<Dummy>
{
}
public interface IProductTypeRepository : IRepository<ProductType>
{
}
public interface IRepository<TEntity> where TEntity : class
{
IList<TEntity> GetAll();
Task<List<TEntity>> GetAllAsync();
Task<List<TEntity>> GetAllAsync(CancellationToken cancellationToken);
IList<TEntity> PageAll(int skip, int take);
Task<List<TEntity>> PageAllAsync(int skip, int take);
Task<List<TEntity>> PageAllAsync(CancellationToken cancellationToken, int skip, int take);
TEntity FindById(object id);
Task<TEntity> FindByIdAsync(object id);
Task<TEntity> FindByIdAsync(CancellationToken cancellationToken, object id);
void Add(TEntity entity);
void Update(TEntity entity);
void Remove(TEntity entity);
}
}
How can I use a same method to mock every repositories implementation which inherits IRepository?
UPDATE :
The test is just a simple add and check like below.
[Test]
public void ProductTypeService_Add()
{
// GIVEN
var productTypeData = new ProductType()
{
Id = 1,
Description = "ProductType1"
};
// WHEN
var unitOfWorkMock = new Helper().MockUnitOfWork();
var productTypeService = new ProductTypeService(unitOfWorkMock.Object);
productTypeService.Add(productTypeData);
unitOfWorkMock.Verify(x => x.SaveChanges());
// THEN
Assert.That(productTypeService.FindById(1) != null);
Assert.That(productTypeService.FindById(2) == null);
// WHEN
var productTypeData2 = new ProductType()
{
Id = 2,
Description = "ProductType2"
};
productTypeService.Add(productTypeData2);
// THEN
Assert.That(productTypeService.FindById(2) != null);
}
IMHO you are testing the wrong thing; namely you are testing that an in-memory collection (a List<T>) can store data and the data can be found in the collection. This always yields true because that is the purpose of in-memory collections.
Instead of doing this you either need to create integration tests which will use the actual implementation of the underlying repository (such as Entity Framework) or just test the behavior of your service like this:
[Test]
public void ProductTypeService_WhenAddingNewItem_CallsSaveChanges()
{
var unitOfWork = new Mock<IUnitOfWork>();
// setup the properties of the mock here...
var service = new ProductTypeService(unitOfWork);
service.Add(new ProductType { Id = 2, Description = "some product" });
unitOfWork.AssertWasCalled(_ => _.SaveChanges());
}
This way, you test that your service calls SaveChanges() method; actually saving the data is the responsibility of the repository and as I said above, testing that a list can store data in memory is useless.
I think you have over complicated your question and thus your solution. You don't need interfaces for your various repositories like IDummyRepository and IProductRepository if you are not adding any value to it.
Your data classes
public class Dummy
{
public int Id { get; set; }
}
public class ProductType
{
public int Id { get; set; }
}
Your ProductTypeService (I can only assume this)
public class ProductTypeService
{
private readonly IUnitOfWork _unitOfWork;
public ProductTypeService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public void AddProductType(ProductType productType)
{
_unitOfWork.ProductTypes.Add(productType);
}
}
Your IUnitOfWork
public interface IUnitOfWork
{
IRepository<Dummy> Dummies { get; set; }
IRepository<ProductType> ProductTypes { get; set; }
}
Your IRepository remains unchanged so I won't copy paste it here!
Finally your unit test
[TestFixture]
public class Class1
{
private Mock<IUnitOfWork> _unitOfWorkMock;
private Mock<IRepository<Dummy>> _dummyRepositoryMock;
private Mock<IRepository<ProductType>> _productTypeRepositoryMock;
[SetUp]
public void Setup()
{
_unitOfWorkMock = new Mock<IUnitOfWork>();
_dummyRepositoryMock = CreateMock<Dummy>();
_productTypeRepositoryMock = CreateMock<ProductType>();
_unitOfWorkMock.Setup(u => u.Dummies).Returns(_dummyRepositoryMock.Object);
_unitOfWorkMock.Setup(u => u.ProductTypes).Returns(_productTypeRepositoryMock.Object);
}
[Test]
public void product_type_service_should_add_item_to_the_underlying_repository()
{
var productTypeService = new ProductTypeService(_unitOfWorkMock.Object);
var productType = new ProductType {Id = 10};
productTypeService.AddProductType(productType);
_productTypeRepositoryMock.Verify(r => r.Add(It.Is<ProductType>(p => p.Id == productType.Id)), Times.Once());
}
private Mock<IRepository<T>> CreateMock<T>() where T : class
{
var mock = new Mock<IRepository<T>>();
// do more common magic here
return mock;
}
}

interfaces and classes in C#

I get the following error:
test.Services.JobService' does not contain a constructor that takes
0 arguments.
this is the code:
JobService.cs:
namespace TesteUltrafan.Services
{
public class JobService
{
private readonly IRepository _repository;
public JobService(IRepository repository)
{
_repository = repository;
}
public Job CreateJobBanker()
{
var banker = new Job();
string id = Guid.NewGuid().ToString("N");
Console.WriteLine("Novo job banker id: {0}", id);
banker.Id = id;
banker.Type = JobType.Banker;
banker.CreatedAt = DateTime.Now;
Console.WriteLine("Salvando job banker id: {0}", id);
Job jobBanker = _repository.SaveJob(banker);
return jobBanker;
}
}
}
the program.cs:
public class Program
{
public static void Main()
{
var jobService = new JobService(); <---- Here is the error.
Console.WriteLine("Creating job banker, creation:");
Job jobBanker = jobService.CreateJobBanker();
Console.WriteLine("Job banker: {0}", jobBanker);
}
}
Job.cs:
public class Job
{
public string Id { get; set; }
public DateTime CreatedAt { get; set; }
public JobType Type { get; set; }
}
JobType.cs:
public enum JobType
{
Actor = 1,
Agricultural = 2,
Banker = 3,
EngineerCivil = 4,
Another = 5,
}
You either need to create a parameterless constructor in your JobService class (which I would not do because then your class will not work correctly - there will be no reference to any repository) or preferably pass a Repository instance as a parameter when constructing this instance.
So the code should preferably look like this:
public class Program
{
public static void Main()
{
var jobService = new JobService(new Repository());
Console.WriteLine("Creating job banker, creation:");
Job jobBanker = jobService.CreateJobBanker();
Console.WriteLine("Job banker: {0}", jobBanker);
}
}
Where Repository should be a class implementing IRepository interface. Without passing this instance your CreateJobBanker will not work.
What would be though recommended is to use some IoC Container, because your code follows the Inversion of Control principle (probably you are not even aware of this).
Use
var jobService = new JobService(new Repository());
because otherwise your JobService with not have an IRepository instance and will throw a NullReferenceException when you try to use your repository inside JobService.
In your code, you are initialising JobService without giving it a IRepository argument, to get your code to compile you need to define a constructor in JobService that does not have an IRepository argument if you want to do that:
public class JobService
{
private readonly IRepository _repository;
// New Constructor will make _repository null
public JobService()
{
}
public JobService(IRepository repository)
{
_repository = repository;
}
public Job CreateJobBanker()
{
var banker = new Job();
string id = Guid.NewGuid().ToString("N");
Console.WriteLine("Novo job banker id: {0}", id);
banker.Id = id;
banker.Type = JobType.Banker;
banker.CreatedAt = DateTime.Now;
Console.WriteLine("Salvando job banker id: {0}", id);
// NullReferenceException if you define a parameterless constructor
Job jobBanker = _repository.SaveJob(banker);
return jobBanker;
}
}
Now you can construct it in two ways:
var jobService = new JobService();
or
var jobService = new JobService(new Repository());
IRepository implementation:
public class Repository: IRepository
{
private MyDbEntities context = new MyDbEntities();
public Job SaveJob(Job job)
{
// assuming Entity Framework
var id = job.Id;
if (context.Jobs.Any(e => e.Id == id))
{
context.Jobs.Attach(job);
context.ObjectStateManager.ChangeObjectState(jobs, EntityState.Modified);
}
else
{
context.Jobs.AddObject(myEntity);
}
context.SaveChanges();
return job;
}
}

Categories