I am making DAO unit tests in my project and I have a problem using the ObjectSet class. I have to create a new ObjectSet but in order to do this, I must not connect to the DB. So I can not use the BusinessModelContainer's CreateObjectSet() method. Is there is a way to create the ObjectSet without it?
The unit test code is like this:
var mock = new Mock<IBusinessModelContainerWrapper>();
ObjectSet<Student> expectedStudent = ???; // how can I get an instance here?
StudentDao studentDao = new StudentDao(mock.Object);
expectedStudent.Add(someObj);
mock.Setup(c => c.Students).Returns(expectedStudent);
Assert.AreEqual(someObj, studentDao.GetByQuery(...));
What are you testing? You should not need instance of real ObjectSet in your unit test unless you are unit testing EF code. Use mock of IObjectSet instead. There is no way to get instance of ObjectSet without the context.
DAL.Moles.MDALEntities.Constructor = (a) => { };
DALEntities db = new DALEntities(); //Object Context
System.Data.Objects.Moles.MObjectContext.AllInstances.CreateObjectSet<ObjectSetType>(
(a) => { return new System.Data.Objects.Moles.MObjectSet<ObjectSetType>(); }
);
ObjectSet<ObjectSetType> dbList = db.CreateObjectSet<ObjectSetType>();
Related
I try to test my app so I need to mock my EF context.
My code seems to be ok, but I have following exception:
"System.ArgumentNullException : Value cannot be null. Parameter name:
source"
Here is my test method:
var options = new DbContextOptionsBuilder<ProductContext>().Options;
var settings = new SqlSettings
{
InMemory = true
};
var context = new Mock<ProductContext>(options, settings);
var mockTreeService = new TreeService(context.Object);
await mockTreeService.CreateTreeAsync("Testing tree", Guid.NewGuid());
context.Verify(x => x.AddAsync(It.IsAny<Tree>(), CancellationToken.None), Times.Once);
It looks like that this exception is thrown during executing this piece of code
var tree = await _context.Trees
.Include(x => x.Translation)
.FirstOrDefaultAsync(x => x.Translation.Pl == name);
It comes from my service which I'm testing
I think this is due to not having a connection string set. Frankly, it's a bit difficult to fully mock out DbContext, which is why the EF Core team has provided an in-memory implementation. This is far easier to work with for testing purposes. Just change your options initialization to:
var options = new DbContextOptionsBuilder<ProductContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
Afterwards, you'll need to populate the database with your test data. Then, you can run the rest of your test.
Note: if you're using the in-memory database, you don't need to mock the context anymore, so you can remove that bit of code. The in-memory database is essentially, itself, a mock.
I have used this https://github.com/huysentruitw/entity-framework-core-mock library. Very easy and can write unit test using less coding.
You can use most of Moq methods if you are using moq framework.
Below is example code for test DBQuerys.
public async Task<Boat> GetByIdAsync(string id)
=> await _boatContext.Boats.Where(x => x.id == id).FirstOrDefaultAsync();
[Fact]
public async Task GetByIdAsync_WhenCalled_ReturnsItem()
{
// Arrange
var models = new[] { new Boat { id = "p1" } };
var dbContextMock = new DbContextMock<BoatContext>();
dbContextMock.CreateDbQueryMock(x => x.Boats, models);
var service = new Properties(dbContextMock.Object);
// Act
var okResult = await service.GetByIdAsync("p1");
// Assert
Assert.IsType<Boat>(okResult.Result);
}
Posting here this may help someone :)
Try to use my Moq/NSubstitute extension MockQueryable: https://github.com/romantitov/MockQueryable
supported all Sync/Async operations
//1 - create a List<T> with test items
var users = new List<UserEntity>()
{
new UserEntity,
...
};
//2 - build mock by extension
var mock = users.AsQueryable().BuildMock();
//3 - setup the mock as Queryable for Moq
_userRepository.Setup(x => x.GetQueryable()).Returns(mock.Object);
//3 - setup the mock as Queryable for NSubstitute
_userRepository.GetQueryable().Returns(mock);
DbSet also supported
//2 - build mock by extension
var mock = users.AsQueryable().BuildMockDbSet();
//3 - setup DbSet for Moq
var userRepository = new TestDbSetRepository(mock.Object);
//3 - setup DbSet for NSubstitute
var userRepository = new TestDbSetRepository(mock);
Note:
AutoMapper supported from 1.0.4 ver
DbQuery supported from 1.1.0 ver
I don't think it's correct to Mock the DbContext. You should be mocking your repositories in your testing... mocking the DbContext is you basically testing Microsoft's code... which is dumb because they already do that. So again... all of your data access should go through repositories (see Repository Pattern) and you should be mocking those in your testing, not the DbContext.
I am trying to write a unit test for a CodeActivity Workflow. My test so far is only
[TestMethod]
public void BusinessUnitTest()
{
WorkflowInvoker invoker = new WorkflowInvoker(new DespatchStockOrder());
invoker.Extensions.Add<ITracingService>(() => tracingService);
invoker.Extensions.Add<IWorkflowContext>(() => workflowContext);
invoker.Extensions.Add<IOrganizationServiceFactory>(() => factory);
IDictionary<string, object> outputs = invoker.Invoke();
}
This works fine and runs the workflow. However I get a null referrence when I hit this line in the workflow.
// Create the context
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
if (context == null)
{
throw new InvalidPluginExecutionException("Failed to retrieve workflow context.");
}
Entity entity = new Entity(context.PrimaryEntityName) //This line errors with PrimaryEntityName null
{
Id = context.PrimaryEntityId,
LogicalName = context.PrimaryEntityName
};
My question is how do I get context.PrimaryEntityName witha value in a unit test
If you are building the context manually then you will need to populate the PrimaryEntityName in the [TestMethod]. You should probably look further into how your workflowContext test object is constructed.
[TestMethod]
public void BusinessUnitTest()
{
workflowContext.PrimaryEntityName = "Entity name";
WorkflowInvoker invoker = new WorkflowInvoker(new DespatchStockOrder());
invoker.Extensions.Add<ITracingService>(() => tracingService);
invoker.Extensions.Add<IWorkflowContext>(() => workflowContext);
invoker.Extensions.Add<IOrganizationServiceFactory>(() => factory);
IDictionary<string, object> outputs = invoker.Invoke();
}
You might want to try FakeXrmEasy. It's an open source unit testing library I'm maintaining to facilitate unit testing for Dynamics Crm without mocking anything.
You get a reference to a workflow context and inject whatever parameters you need, including Primary Entity names and Id's.
But the most common crm messages are already mocked (retrieve multiple requests, CRUD, fetchxml, LINQ, QueryExpressions, and so no...)
I'm trying out Moq and the builder pattern to set up services for testing CRM plugins. On the builder I have a ConfigureMock<T>(Expression<Action<Mock<T>>>) to inject individual configurations. My problem is that once a service is .Setup(), I would like to get the entity the service worked on via .Callback<Entity>(), but I cannot assign it to a local variable in the test, because I can't do assignments in the callback expression.
Here is the config:
private readonly Dictionary<Type, object> MockServices = new Dictionary<Type, object>();
public PluginContextBuilder ConfigMock<T>(Expression<Action<Mock<T>>> setupConfig) where T : class
{
object svc = null;
if (MockServices.TryGetValue(typeof(T), out svc))
{
var mockSvc = (Mock<T>) svc;
Action<Mock<T>> setup = setupConfig.Compile();
setup(mockSvc);
}
return this;
}
And here's an example how I would like to configure in the test (but will not compile):
var createdFanClub = null;
var context = new PluginContextBuilder()
.ConfigMock<IOrganizationService>(c =>
c.Setup(s =>
s.Create(It.IsAny<Entity>()))
.Returns(fanclubGuid))
.Callback<Entity>(a => createdFanClub = a))
If I create an additional Action<Entity> which does the assignment, it works, but I don't think it's practical, in case I have multiple entities, I will need to make just as many assignments for them:
Entity createdFanClub = null;
Action<Entity> assign = a => createdFanClub = a;
var context = new PluginContextBuilder()
.ConfigMock<IOrganizationService>(c =>
c.Setup(s =>
s.Create(It.IsAny<Entity>()))
.Returns(fanclubGuid))
.Callback<Entity>(assign))
Not sure what you try to accomplish. If the goal is to have a builder, which has a handle to all the mocks needed, then why not just return the mock itself, and configure it as one normally will do:
builder.GetMock<IOrganizationService>().Setup....
That will prevent you to chain calls on the same builder (as I see you are trying to do), but it's not a big trade-off, and will simplify your setups.
I'm thinking something like this:
IUoW oUoW = oUnity.Resolve<IUoW>(); //<-- New Context here (Life per resolve).
var oNewEntity = new SomeEntity{ name = "somethink ... "};
oUoW.oSomeEntity.Add( oNewEntity);
oUoW.SaveChanges();
oUoW.Dispose();//<-- delete context.
But how can I resolve the instance for "oUoW.oSomeEntity", I could need to do a Resolve in the constructor or not...
Another way I'm thinking
IUoW oUoW = oUnity.Resolve<IUoW>(); //<-- New Context here (Life per resolve).
var oNewEntity = new SomeEntity{ name = "somethink ... "};
oSomeEntityRepository = oUnity.Resolve<ISomeEntityRepository>();//Ugly way
oSomeEntityRepository.oUoW = oUoW;//Ugly way
oSomeEntityRepository.Add( oNewEntity);
oUoW.SaveChanges();
oUoW.Dispose();//<-- Delete context.
... Open Another Context ...
That's code is not thread safe 100%, but I would short instances of context
Do you think another way?
I'll Do Unit Test now ...
To thread safe I'm thinking in another method that use a Mutex ... something like...
IUoW oUoW = oUnity.Resolve<IUoW>();
oUoW.MutexLock();
... save, delete, linq ...
oUoW.MutexUnlok();
mmm .... &%$··%&·!&$%&...mmm LAPSUS
As soon as you have your uow resolved, repositories should be direct properties of the uow:
IUoW oUoW = oUnity.Resolve<IUoW>(); //<-- New Context here (Life per resolve).
var oNewEntity = new SomeEntity{ name = "somethink ... "};
oSomeEntityRepository = uow.SomeEntityRepository;//Not ugly at all
Since most example implementations follow this idea, I wonder what your implementation is.
Anyway, it goes like
public class UnitOfWork
{
private ISomeEntityRepository _someEntityRepository;
public ISomeEntityRepository SomeEntityRepository
{
get
{
if ( _someEntityRepository == null )
_someEntityRepository = new ...
return _someEntityRepository;
}
#Wiktor Zychla is right but I his example implemetation can confuse you. If you are using a DI container, like Unity here, repositories should be injected in UOW when UOW is resolved; and a single DBContext instance injected in UOW (to call saveChanges) and in all repositores resolved (I assume that your UOW has multiple repositories becuase if not, you do not need UOW). This is know as "cascade injection" and is the butter and bread of using a DI container.
This way you can make multiple changes in Database using multiple repositories (one for aggregate root) to finish a use case and only a single UOW.Savechanges needed.
Well, I've edited a template that auto-generate a UnitOfWork, Context, Repository, And FactoryUnitOfWork http://pastebin.com/6D2X5Ykp, you need to edit the template to change the entity model if you do it in a separate dll.
To use the Pattern:
Register in Composition Root:
IUnityContainer uc = new UnityContainer();
yourdaonamespace.CompositionRoot.Init( uc );
And to use:
using (var oIUoW = this.IFactoryUnitOfWork.Resolve())
{
var YOURENTITYFoundedFromRepository = oIUoW.oRepositoryENTITY.First(o => o.iYourProperty == 1);
}
//more code
using (var oIUoW = this.IFactoryUnitOfWork.Resolve())
{
var entity = new domain.YOURENTITY()
{
sYourProperty = "TEST ENTITY"
};
uow.oRepositoryYOURENTITY.Insert(entity);
uow.Commit();
}
Requirement: Your need to generate the YOURMODEL.edmx
NOTE: The Template Is Temporal In Pastebin, Could Anyone Help With Permanent Template, Thanks!
I am starting a new project with NHibernate, ASP.NET MVC 2.0 and StructureMap and using NUnit and Moq for testing. For each of my controllers I have a single public constructor into which an ISession is being injected. The application itself works just fine, but in terms of unit testing I essentially have to mock an ISession in order to test the controllers.
When I attempt to Mock the ISession with MOQ i get the following error message:
Only property accesses are supported
in intermediate invocations
It appears that my problem is expecting List of users from the framework CreateQuery method but after googling the issue I am now clearer.
I have two questions:
1) Is this the WRONG way to mock dependency injection of an ISession
2) Is there a way to modify the code so that it can successfully return my list
[Test]
public void DummyTest()
{
var mock = new Mock<ISession>();
var loc = new Mock<User>();
loc.SetupGet(x => x.ID).Returns(2);
loc.SetupGet(x => x.FirstName).Returns("John");
loc.SetupGet(x => x.LastName).Returns("Peterson");
var lst = new List<User> {loc.Object};
mock.Setup(framework => framework.CreateQuery("from User").List<User>()).Returns(lst);
var controller = new UsersController(mock.Object);
var result = controller.Index() as ViewResult;
Assert.IsNotNull(result.ViewData);
}
Please note, I am pretty sure I could just create a hard-coded list of users (rather than mocking an individual User and adding it to a list) but figured I'd leave the code as I have it right now.
Also, the Index action of this particular controller essentially executes the CreateQuery call mimicked above to return all users in the database. This is a contrived example - don't read anything into the details.
Thanks in advance for your help
Edit: In reply to the below comment, I am adding the stacktrace for the error. Also, all properties on the User class are virtual.
TestCase
'Beta.Tests.Unit.Controllers.UserControllerTest.Details_InValidIndex_ReturnsNotFoundView'
failed: System.NotSupportedException :
Only property accesses are supported
in intermediate invocations on a
setup. Unsupported expression
framework.CreateQuery("from User").
at
Moq.Mock.AutoMockPropertiesVisitor.VisitMethodCall(MethodCallExpression
m) at
Moq.ExpressionVisitor.Visit(Expression
exp) at
Moq.Mock.AutoMockPropertiesVisitor.VisitMethodCall(MethodCallExpression
m) at
Moq.ExpressionVisitor.Visit(Expression
exp) at
Moq.Mock.AutoMockPropertiesVisitor.SetupMocks(Expression
expression) at
Moq.Mock.GetInterceptor(LambdaExpression
lambda, Mock mock) at
Moq.Mock.<>c__DisplayClass122.<Setup>b__11()
at Moq.PexProtector.Invoke[T](Func1
function) at
Moq.Mock.Setup[T1,TResult](Mock mock,
Expression1 expression) at
Moq.Mock1.Setup[TResult](Expression`1
expression)
Controllers\UserControllerTest.cs(29,0):
at
Beta.Tests.Unit.Controllers.UserControllerTest.Details_InValidIndex_ReturnsNotFoundView()
Below is the solution I came up with which seems to work perfectly. Again, I am not testing NHibernate and I am not testing the database - I simply want to test the controllers which depend on NHibernate. The issue with the initial solution appears to be the fact that I was calling a Method as well as reading the List member of the session in the MOQ setup call. I broke up these calls by breaking the solution into a QueryMock and a Session Mock (create query returns an IQuery object). A transaction mock was also necessary as it is a dependency (in my case) of the session...
[Test]
public void DummyTest()
{
var userList = new List<User>() { new User() { ID = 2, FirstName = "John", LastName = "Peterson" } };
var sessionMock = new Mock<ISession>();
var queryMock = new Mock<IQuery>();
var transactionMock = new Mock<ITransaction>();
sessionMock.SetupGet(x => x.Transaction).Returns(transactionMock.Object);
sessionMock.Setup(session => session.CreateQuery("from User")).Returns(queryMock.Object);
queryMock.Setup(x => x.List<User>()).Returns(userList);
var controller = new UsersController(sessionMock.Object);
var result = controller.Index() as ViewResult;
Assert.IsNotNull(result.ViewData);
}
Rather than mocking the Session, one might consider setting up a different Configuration for unit-tests. This unit-testing Configuration uses a fast, in-process database like SQLite or Firebird. In the fixture setup, you create a new test database completely from scratch, run the scripts to set up the tables, and create a set of initial records. In the per-test setup, you open a transaction and in the post-test teardown, you rollback the transaction to restore the database to its previous state. In a sense, you are not mocking the Session, because that gets tricky, but you are mocking the actual database.