I have two [TestMethods]. The result of MethodA needs to be the input of MethodB. The problem is that all values and variables are reset when a new test method starts.
Somebody has already asked the exact same question, but there was no real solution yet.
All I want is the following to work:
Guid CustomerID;
[TestMethod]
public void CreateCustomer()
{
// Create a new customer and store the customer id
CustomerID = CreateNewCustomer();
Assert.IsNotNull(...);
}
[TestMethod]
public void DeleteCustomer()
{
// Delete the customer created before
var ok = DeleteCustomer(CustomerID);
Assert.IsNotNull(...);
}
I understand that this is not the "official" way for testing, but I really need a practical solution for this scenario -so I am hoping for some kind of workaround.
Any ideas?
Why not create the customer in your delete customer test?
[TestMethod]
public void CreateCustomer()
{
// Create a new customer and store the customer id
var customerID = CreateNewCustomer();
Assert.IsNotNull(...);
}
[TestMethod]
public void DeleteCustomer()
{
// Delete the customer created before
var customerID = CreateNewCustomer();
var ok = DeleteCustomer(customerID);
Assert.IsNotNull(...);
}
or just create the customer in the testfixture set up:
(The name of the TestFixtureSetUp might be different in VS test environment, that is what it is called in NUnit, but there will be an equivalent)
private Guid CustomerID;
[TestFixtureSetUp]
{
**EDIT** you could ensure you DB is clean here:
CleanDB();
CustomerID = CreateNewCustomer();
}
[TestMethod]
public void CreateCustomer()
{
// check previously created customer
Assert.IsNotNull(...);
}
[TestMethod]
public void DeleteCustomer()
{
// Delete the customer created before
var ok = DeleteCustomer(CustomerID);
Assert.IsNotNull(...);
}
[TestFixtureTearDown]
{
**EDIT** or you could ensure you DB is clean here:
CleanDB();
}
The first solution is better in my opinion as each test is responsible for creating its own data, but if this is an integration test which is actually putting stuff into and out of the database then it is ok (again in my opinion) to have the data needed for all tests to be done in the setup for that class and then all tests can run expecting the data to be there. You should ensure though that each test class also has a corresponding test tear down which will remove this classes test data from the db, or that you are cleaning the DB somewhere before each test class is run (like in a common base class)
You need to use [TestInitialize] method for test prerequisities as in your case for creating new customer because each [TestMethod] is ran standalone.
Related
My Audit logs are getting out of hand so I decided I want to only audit all requests which basically are not a Get request. Is there a very simply way to do this from configuration?
The documentation here:
https://aspnetboilerplate.com/Pages/Documents/Audit-Logging
Says:
Note: In addition to the standard audit configuration, MVC and ASP.NET
Core modules define configurations to enable/disable audit logging for
actions.
But I could not find more information about what exactly this means.
As a last resort, I know it would work if I went to every class and added [DisableAuditing] and then [Audited] on the non-Get endpoints, but that seems a bit messy.
Best soltuion: I just want to have a simply way to select only non-GET requests and audit them.
Second best solution:
I just want to have only [Audited] methods audited. I don't want to have to go and write [DisabledAuditing] on every class.
You can create an AuditStore to do that, and then replace the original AuditStore in service YourAplicationNameCoreModule
Here is the example
public class YourAuditStore : AuditingStore
{
public ILogger<AuditingStore> Logger { get; set; }
private readonly IRepository<AuditLog, long> _auditLogRepository;
private readonly ISettingManager _settingManager;
public YourAuditStore(IRepository<AuditLog, long> auditLogRepository, ISettingManager settingManager) : base(auditLogRepository)
{
_auditLogRepository = auditLogRepository;
_settingManager = settingManager;
}
public override async Task SaveAsync(AuditInfo auditInfo)
{
AuditLog auditLog = new AuditLog();
bool logErrorsOnly = await _settingManager.GetSettingValueAsync<bool>(AppSettings.Logging.LogOnErrorsOnly);
var exceptionMessage = auditInfo.Exception != null ? auditInfo.Exception.ToString() : null;
if ((logErrorsOnly && exceptionMessage != null) || !logErrorsOnly)
{
auditLog = await _auditLogRepository.InsertAsync(AuditLog.CreateFromAuditInfo(auditInfo));
}
}
}
As you can see, you can filter whatever you want in SaveAsync method as it recieve the AuditInfo, you can check if method is different to Get then save
Add the next code to YourApplicationNameCoreModule on PreInitialize method
public override void PreInitialize()
{
Configuration.ReplaceService<IAuditingStore, YourAuditStore>();
}
I've created an MVC.net application using EF and the Unit of work pattern. I followed this tutorial to create the unit of work classes:
http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
I'm trying to create a report using the report viewer control. I understand MVC pages don't currently support the report viewer control so I've created a standard aspx page with the report viewer control. I'm new to reports and I've been following this tutorial:
http://weblogs.asp.net/rajbk/archive/2010/05/09/creating-an-asp-net-report-using-visual-studio-2010-part-1.aspx
However when I add the object data source to the page and try to select the repository, my repository is not listed. The unit of work class is listed but has no methods available
Figured I'd post my progress in case it helps anybody else.
First I created a stored procedure in the SOL database to get the records for the report with optional parameters for filtering.
Then I updated the edmx diagram to import the stored procedure and create a new complex class for the returned records.
Finally I created new report repository that sits outside the unit of work, like so:
namespace Project.DAL
{
public class ReportRepository : IDisposable
{
internal ProjectEntities context;
public ReportRepository()
{
this.context = new ProjectEntities();
}
public ReportRepository(ProjectEntities context)
{
this.context = context;
}
public List<Report_001_Result> Report001(string Status, DateTime? dateOpenedFrom, DateTime? dateOpenedTo, string caseTypeD, string subCaseType)
{
return this.context.Report_001(caseStatusID, dateOpenedFrom, dateOpenedTo, caseTypeID, subCaseTypeID).ToList();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
Once the project has been built the Report repository shows up the data selection lists for object datasources and in the report designer.
For each report i just add another method to this repository.
Not sure if this is the prefered approach but works for me.
I'm getting into writing unit testing and have implemented a nice repository pattern/moq to allow me to test my functions without using "real" data. So far so good.. However..
In my repository interface for "Posts" IPostRepository I have a function:
Post getPostByID(int id);
I want to be able to test this from my Test class but cannot work out how.
So far I am using this pattern for my tests:
[SetUp]
public void Setup()
{
mock = new Mock<IPostRepository>();
}
[Test]
public void someTest()
{
populate(10); //This populates the mock with 10 fake entries
//do test here
}
In my function "someTest" I want to be able to call/test the function GetPostById. I can find the function with mock.object.getpostbyid but the "object" is null.
Any help would be appreciated :)
iPostRepository:
public interface IPostRepository
{
IQueryable<Post> Posts {get;}
void SavePost(Post post);
Post getPostByID(int id);
}
I'm not sure what unit testing framework you are using, but I am using NUnit. I'm not a unit testing pro, but I know enough to get me started and to get results.
I normally have a service layer, and this will call my post repository:
public class PostService
{
private readonly IPostRepository postRepository;
public PostService(IPostRepository postRepository)
{
if (postRepository== null)
{
throw new ArgumentNullException("postRepository cannot be null.", "postRepository");
}
this.postRepository = postRepository;
}
public Post GetPostById(int id)
{
return postRepository.GetPostById(id);
}
}
Your unit tests could look like this:
[TestFixture]
public class PostServiceTests
{
private PostService sut;
private Mock<IPostRepository> postRepositoryMock;
private Post post;
[SetUp]
public void Setup()
{
postRepositoryMock = new Mock<IPostRepository>();
sut = new PostService(postRepositoryMock.Object);
post = new Post
{
Id = 5
};
}
[Test]
public void GetPostById_should_call_repository_to_get_a_post_by_id()
{
int id = 5;
postRepositoryMock
.Setup(x => x.GetPostById(id))
.Returns(post).Verifiable();
// Act
Post result = sut.GetPostById(id);
// Assert
Assert.AreEqual(post, result);
postRepositoryMock.Verify();
}
}
I hope this helps.
If you want your mock object to return a result (not null), you need to set it up:
mock.Setup( m => m.GetPostByID( 5 ) ).Returns( new Post() );
What you return exactly is up to you of course.
Update:
If you need to use the method parameters you can also setup a CallBack. For example:
mock.Setup( m => m.GetPostByID( It.IsAny<int>() ) )
.Callback( id => return new Post{ Id = id; } );
This may make your setup code much easier since you don't need to prime the mock with data.
If you want to test the real implementation of GetPostById, do so via the real implementation of IPostRepository. Moq (and mocks in general) are only for situation where you don't want to use the real thing.
In other words prime your database with some posts, new up the real repository, call GetPostById and make assertions on the result. This is not strictly a unit test though, but an integration test because it includes the database.
Most of my knowledge of ASP.NET MVC 3 comes from reading through the book Pro ASP.NET MVC 3 Framework by Adam Freeman and Steven Senderson. For my test application I have tried to stick to their examples very closely. I am using the repository pattern plus Ninject and Moq which means that unit testing work quite well (i.e. without needing to pull data from the database).
In the book repositories are used like this:
public class EFDbTestChildRepository
{
private EFDbContext context = new EFDbContext();
public IQueryable<TestChild> TestChildren
{
get { return context.TestChildren; }
}
public void SaveTestChild(TestChild testChild)
{
if (testChild.TestChildID == 0)
{
context.TestChildren.Add(testChild);
}
else
{
context.Entry(testChild).State = EntityState.Modified;
}
context.SaveChanges();
}
}
And here is the DbContext that goes with it:
public class EFDbContext : DbContext
{
public DbSet<TestParent> TestParents { get; set; }
public DbSet<TestChild> TestChildren { get; set; }
}
Please note: to keep things simple in this extracted example I have left out the interface ITestChildRepository here which Ninject would then use.
In other sources I have seen a more general approach for the repository where one single repository is enough for the whole application. Obviously in my case I end up with quite a list of repositories in my application - basically one for each entity in my domain model. Not sure about the pros and cons about the two approaches - I just followed the book to be on the safe side.
To finally get to my question: each repository has its own DbContext - private EFDbContext context = new EFDbContext();. Do I risk ending up with multiple DbContexts within one request? And would that lead to any significant performance overhead? How about a potential for conflicts between the contexts and any consequences to the data integrity?
Here is an example where I ended up with more than one repository within a controller.
My two database tables are linked with a foreign key relationship. My domain model classes:
public class TestParent
{
public int TestParentID { get; set; }
public string Name { get; set; }
public string Comment { get; set; }
public virtual ICollection<TestChild> TestChildren { get; set; }
}
public class TestChild
{
public int TestChildID { get; set; }
public int TestParentID { get; set; }
public string Name { get; set; }
public string Comment { get; set; }
public virtual TestParent TestParent { get; set; }
}
The web application contains a page that allows the user to create a new TestChild. On it there is a selectbox that contains a list of available TestParents to pick from. This is what my controller looks like:
public class ChildController : Controller
{
private EFDbTestParentRepository testParentRepository = new EFDbTestParentRepository();
private EFDbTestChildRepository testChildRepository = new EFDbTestChildRepository();
public ActionResult List()
{
return View(testChildRepository.TestChildren);
}
public ViewResult Edit(int testChildID)
{
ChildViewModel cvm = new ChildViewModel();
cvm.TestChild = testChildRepository.TestChildren.First(tc => tc.TestChildID == testChildID);
cvm.TestParents = testParentRepository.TestParents;
return View(cvm);
}
public ViewResult Create()
{
ChildViewModel cvm = new ChildViewModel();
cvm.TestChild = new TestChild();
cvm.TestParents = testParentRepository.TestParents;
return View("Edit", cvm);
}
[HttpPost]
public ActionResult Edit(TestChild testChild)
{
try
{
if (ModelState.IsValid)
{
testChildRepository.SaveTestChild(testChild);
TempData["message"] = string.Format("Changes to test child have been saved: {0} (ID = {1})",
testChild.Name,
testChild.TestChildID);
return RedirectToAction("List");
}
}
catch (DataException)
{
//Log the error (add a variable name after DataException)
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
}
// something wrong with the data values
return View(testChild);
}
}
It's not enough to have an EFDbTestChildRepository available but I also need an EFDbTestParentRepository. Both of them are assigned to private variables of the controller - and voila, it seems to me that two DbContexts have been created. Or is that not correct?
To avoid the issue I tried using EFDbTestChildRepository to get to the TestParents. But that obviously will only bring up those that are already hooked up to at least one TestChild - so not what I want.
Here is the code for the view model:
public class ChildViewModel
{
public TestChild TestChild { get; set; }
public IQueryable<TestParent> TestParents { get; set; }
}
Please let me know if I forgot to include some relevant code. Thanks so much for your advice!
There won't be a performance problem (unless we are talking about nanoseconds, instantiating a context is very cheap) and you won't have damaged your data integrity (before that happens you'll get exceptions).
But the approach is very limited and will work only in very simple situations. Multiple contexts will lead to problems in many scenarios. As an example: Suppose you want to create a new child for an existing parent and would try it with the following code:
var parent = parentRepo.TestParents.Single(p => p.Id == 1);
var child = new Child { TestParent = parent };
childrenRepo.SaveTestChild(child);
This simple code won't work because parent is already attached to the context inside of parentRepo but childrenRepo.SaveTestChild will try to attach it to the context inside of childrenRepo which will cause an exception because an entity must not be attached to another context. (Here is actually a workaround because you could set the FK property instead of loading the parent: child.TestParentID = 1. But without a FK property it would be a problem.)
How to solve such a problem?
One approach could be to extend the EFDbTestChildRepository by a new property:
public IQueryable<TestParent> TestParents
{
get { return context.TestParents; }
}
In the example code above you could then use only one repository and the code would work. But as you can see, the name "EFDbTest Child Repository" doesn't really fit anymore to the purpose of the new repository. It should be now "EFDbTest ParentAndChild Repository".
I would call this the Aggregate Root approach which means that you create one repository not for only one entity but for a few entities which are closely related to each other and have navigation properties between them.
An alternative solution is to inject the context into the repositories (instead of creating it in the repositories) to make sure that every repository uses the same context. (The context is often abstracted into a IUnitOfWork interface.) Example:
public class MyController : Controller
{
private readonly MyContext _context;
public MyController()
{
_context = new MyContext();
}
public ActionResult SomeAction(...)
{
var parentRepo = new EFDbTestParentRepository(_context);
var childRepo = new EFDbTestChildRepository(_context);
//...
}
protected override void Dispose(bool disposing)
{
_context.Dispose();
base.Dispose(disposing);
}
}
This gives you a single context per controller you can use in multiple repositories.
The next step might be to create a single context per request by dependency injection, like...
private readonly MyContext _context;
public MyController(MyContext context)
{
_context = context;
}
...and then configuring the IOC container to create a single context instance which gets injected into perhaps multiple controllers.
Do I risk ending up with multiple DbContexts within one request?
Yes. Each instance of a repository is going to instantiate its own DbContexts instances. Depending on the size and use of the application, this may not be a problem although it is not a very scalable approach. There are several ways of handling this though. In my web projects I add the DbContext(s) to the Request's Context.Item collection, this way it is available to all classes that require it. I use Autofac (similar to Ninject) to control what DbContexts are created within specific scenarios and how they are stored, e.g. I have a different 'session manager' for a WCF context to the one for a Http context.
And would that lead to any significant performance overhead?
Yes, but again not massively if the application is relatively small. As it grows though, you may notice the overhead.
How about a potential for conflicts between the contexts and any
consequences to the data integrity?
One of the reasons for using an ORM like this is so that changes can be maintained within the DbContext. If you are instantiating multiple context instances per request you lose this benefit. You wouldn't notice conflicts or any impact of the integrity per se unless you were handling a lot of updates asynchronously.
As promised I post my solution.
I came across your question because I was having trouble with the IIS application pool memory growing beyond limits and having multiple DBContexts was one of my suspects. In retrospect it is fair to say that there were other causes for my trouble. However, it challenged me to find a better layer based design for my repository.
I found this excellent blog: Correct use of Repository and Unit Of Work patterns in ASP.NET MVC leading me to the right direction. The redesign is based on the UnitOfWork pattern. It enables me to have just one constructor parameter for all my controllers instead of "never ending constructor parameters". And after that, I was able to introduce proactive caching as well, which solved a great deal of the earlier mentioned trouble I was having.
Now I only have these classes:
IUnitOfWork
EFUnitOfWork
IGenericRepository
EFGenericRepository
See the referred blog for complete information and implementation of these classes. Just to give an example, IUnitOfWork contains repository definitions for all entities that I need, like:
namespace MyWebApp.Domain.Abstract
{
public interface IUnitOfWork : IDisposable
{
IGenericRepository<AAAAA> AAAAARepository { get; }
IGenericRepository<BBBBB> BBBBBRepository { get; }
IGenericRepository<CCCCC> CCCCCRepository { get; }
IGenericRepository<DDDDD> DDDDDRepository { get; }
// etc.
string Commit();
}
}
The Dependency Injection (DI) is just one statement (I use Ninject):
ninjectKernel.Bind<IUnitOfWork>().To<EFUnitOfWork>();
The Controllers-constructors are maintainable:
public class MyController : BaseController
{
private MyModel mdl = new MyModel();
private IUnitOfWork _context;
public MyController(IUnitOfWork unitOfWork)
{
_context = unitOfWork;
// intialize whatever needs to be exposed to the View:
mdl.whatever = unitOfWork.SomeRepository.AsQueryable();
}
// etc.
Within the Controller I can use _context to access all repositories, if needed. The nice part of it, is that it needs just a single Commit()-call to save changed data for all repositories:
_context.Commit();
I have a CRUD repository as fallowing:
public class CrudRepository<T> : ICrudRepository<T>
where T : class, IUnique
{
static DataContext db = new DataContext();
protected DataContext DataContext { get { return db; } }
public virtual IQueryable<T> GetAll()
{
return db.GetTable<T>();
}
public virtual void Add(T item)
{
db.GetTable<T>().InsertOnSubmit(item);
}
public virtual void Save()
{
db.SubmitChanges();
}
public virtual T Get(int id)
{
return GetAll().FirstOrDefault(t => t.Id.Equals(id));
}
}
I use static data context for all instance off repository.
I want to change foreign key entity so i try fallowing solution:
CrudRepository<Employee> employeeRepository = new CrudRepository<Employee >();
Employee employee = employeeRepository.Get(employeeId)
employee.OfficeId = officeId;
employeeRepository.Save();
But it throw fallowing exception :
ForeignKeyReferenceAlreadyHasValueException
So i try fallowing second solution:
CrudRepository<Employee> employeeRepository = new CrudRepository<Employee >();
Employee employee = employeeRepository.Get(employeeId)
employee.Office = new CrudRepository<Office>().Get(officeId);
employeeRepository.Save();
But it throw exception with fallowing message:
An attempt has been made to Attach or
Add an entity that is not new, perhaps
having been loaded from another
DataContext
what can i do?
what is the problem?
Three things jump out at me.
employee.OfficeId = officeId;
If the Employee class has an OfficeId property and an Office property, you must use the Office property to make changes. The Office property is auto-generated from the relationship in the linq designer.
If you want to use Id based manipulations instead, delete the relationship between employee and office in the designer (note: this does not change the database, it just changes the mappings used by the code generator).
new CrudRepository<Employee >();
new CrudRepository<Office>().Get(officeId);
Each Crud Repository has its own datacontext. Objects loaded from different datacontexts are not allowed to co-mingle. Suppose they were allowed to co-mingle - when you call SubmitChanges, which DataContext is responsible for saving?
Ultimately, this means your CrudRepository implementation is going to be something you want to move away from if you want to continue using LinqToSql. Supporting Crud operations on a single class just isn't that useful. At least it's only passthrough calls, and will be easy to replace with direct DataContext method calls.
static DataContext db = new DataContext();
This is damnable. DataContext is not threadsafe.