In some my project I notice that during executing unit tests under VSTS2008 its VSTestHost's memory consuming grows. As I have very many tests in my solution it leads to OutOfMemroyException eventually.
That looks very strange for me as I was sure that MSTest creates a new AppDomain for each unit test. Otherwise how would it reset static fields?
But if AppDomain is being created for each test than memory shouldn't leak. But it does.
So the question is: Should VS create AppDomain for each test class or not? If yes than how can I check that it does it.
I tried tracing through ProcessExpolorer and Performance snap-in. A value of "Total appdomain unloaded" is always 0 during test run.
MsTest creates one-app domain per Test assembly, unless you are using noisolation, in which case there is no AppDomain Isolation.
If you are seeing leaks, its probably a but in either your test code, or your product code. Make sure you aren't stuffing things into dictionaries and leaving them there.
I don't think the unit test engine creates a new AppDomain for each test. Since creating an AppDomain is a relatively expensive operation, doing so for each test would slow down execution of unit tests considerably!
Visual Studio 2008 uses a seperate executable called vstesthost.exe to run unit tests. VS communicates with vstesthost.exe (how it does this I don't know) to tell it what tests to run. vstesthost.exe returns the execution results to VS which displays those results.
If you are getting OutOfMemoryExceptions when running your unit tests I would say that's a strong indicator that your code under test is actually not cleaning things up. Are you sure that you aren't retaining handles to unmanaged objects/memory? I would recommend running your unit tests under a Performance Analysis (you can do that by finding the unit test under the "Test View", right-clicking on it, and selecting "Create Performance Session"). This might shed some light at least on your object allocations.
I was wrong about having separate AppDomains for each unittest.
Here's evidence:
a singleton
public class Singleton
{
public static Singleton Instance = new Singleton();
private Guid _token;
private Singleton()
{
_token = Guid.NewGuid();
}
public Guid Token
{
get { return _token; }
}
}
and two tests:
[TestClass]
public class UnitTest2
{
[TestMethod]
public void TestMethod1()
{
Console.WriteLine(Singleton.Instance.Token);
}
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
Console.WriteLine(Singleton.Instance.Token);
}
}
During executing both tests output the same guid.
Seen the same problem with large test runs. My theory is the following. Memory exhaustion in this case is due to the fact that MSTest test result files are XML. Therefore it needs to keep all the log results in memory until the end of the test run before serializing to disk. Hurray for XML :-)
I have posted this problem as a connect issue a while back and it should have been fixed in MSTest 10 (going 64 bit) but I haven't been able to verify this yet because of all the other problems we have moving to VS2010 and .NET 4.0.
The only way to dispose of a singleton is to dispose the appDomain. A singleton is a static holding onto itself, so it's basically a circular reference. True singletons do not get disposed until the appdomain goes away.
This does not seem to be solved in MSTest 2010. I am experiencing a lot of similar issues like this. Why does garbage collection not work in unit test?
My understanding was that the UT framework took care of disposing of all executed tests, but this does not seem to be the case with some singleton patterns that we have in code.
Related
While running unit test in Visual studio , i was getting 0 Total Tests - 0 passed,0 failed ,0 skipped even after having tests in the class.
In Nunit, if there is an exception in loading test setup or execution it will result in above. From Visual studio menu open debug=>output and select Test window and see are there any exceptions thrown when tests are run. In my case in project1 i have nunit2 (refernce), in project2 i have nunit3 which referred project1 which is causing conflict and unable to execute.
if you resolve the exception it should work
Check if you have runsettings file in your solution or if there is one selected under
VS -> Test -> Configure Run Settings. If this is chosen, uncheck it. Remove the file. This fixed for me.
Ensure the access modifier of the class is public instead of internal. If it is internal none of the [Fact]s in the class will register as tests within the Test Explorer, nor will they run.
Installing Microsoft.NET.Test.Sdk package from nuget package manager solved my issue.
I also have xunit and xunit.runner.visualstudio package installed.
In Case anyone is still struggling with this, installing "MSTest.TestAdapter" solved my issue.
For me a simple "Clean Solution" worked.
Here in my case the issue was different . In VS Unit tests are being identified based on Test class. In my case , there were no access modifier for the class and which caused the issue .VS unable to identify the test methods for the particular class.
class ControllerTests
{
public Controller _Controller;
[TestMethod()]
}
After adding public to the class ,it worked fine.
Public class ControllerTests
{
public Controller _Controller;
[TestMethod()]
}
For MSTest users - if you have a method marked with the [ClassInitialize] attribute, make sure that it is both public and static, and has a single parameter of type TestContext, otherwise the test file will not run.
[ClassInitialize]
public static void ClassInitialize(TestContext testContext)
{
// initialization code...
}
For C#/.NET Playwright:
I've seen this a couple times and my issue was that the return type of an async test method was void, instead of Task. It should be as follows:
[TestMethod]
public async Task TestMethod1()
{
I'm trying to implement integration testing in my app and have test class like that:
#ExtendWith(value={MyDockerExtension.class})
#ExtendWith(value={SpringExtension.class})
#WebAppConfiguration
#ContextConfiguration(classes={...})
#TestInstance(TestInstance.LifeCycle.PER_CLASS)
public class TestClass{ ... }
Is there any way to make MyDockerExtension execute some code, before whole SpringExtension start working and generate whole Context with Configurationc classes?
I've heard that order in which we declare extensions is the key, but sadly MyDockerExtension that implements BeforeAllCallback, AfterAllCallback executes right before test method and after whole context is loaded. In that situation it's to late to start containers with docker, becuase since whole context is loaded my app already tried to connect to the container.
At first I was skeptical about the order being fixed but you're correct:
Extensions registered declaratively via #ExtendWith will be executed in the order in which they are declared in the source code.
Regarding the MyDockerExtension, you may want to look at the extension point TestInstancePostProcessor, which is called before #BeforeAll. SpringExtension implements it and I guess it's there where it sets up the application context. If you also implement it, you should be able to act before it does.
Any unit test the includes a call to SELECT (using LINQ) data from my DBContext throws the following error:
The model backing the 'MyDBContext' context has changed since the
database was created. Either manually delete/update the database, or
call Database.SetInitializer with an IDatabaseInitializer instance.
For example, the DropCreateDatabaseIfModelChanges strategy will
automatically delete and recreate the database, and optionally seed it
with new data.
Doing a search for that specific error leads me to believe that I need to include the following line in my Global.asax Application_Start method:
System.Data.Entity.Database.SetInitializer<MyDBContext>( null );
This is suppose to fix a similar error when running the application itself. Unfortunately, I don't get this error when I run my application and there doesn't seem to be an Application_Start method for my unit test project. Is there any way to to the unit test project that I'm using a custom database back-end and to ignore any changes that have occurred in it?
I added the unit test project after working on my main project for a while so it's possible I messed it up somehow, but I can't figure out for the life of me what to do. I'm using the built in unit testing in Visual Studio 2010.
There are 2 methods that you could use with the VS unit testing framework allowing you to run some code before and after each test and before and after all the tests contained in the file
// Use TestInitialize to run code before running each test
[TestInitialize()]
public void MyTestInitialize()
{
}
// Use TestCleanup to run code after each test has run
[TestCleanup()]
public void MyTestCleanup()
{
}
or:
// Use ClassInitialize to run code before running the first test in the class
[ClassInitialize()]
public static void MyClassInitialize(TestContext testContext)
{
}
// Use ClassCleanup to run code after all tests in a class have run
[ClassCleanup()]
public static void MyClassCleanup()
{
}
In my application I have a set of of DAOs which I inject into my application layer. For an acceptance test I'm writing, I want to preload the dev_server datastore with data, so I use the same Spring config in my JUnit test (using the #ContextConfiguration annotation) to inject an instance of the relevant DAO into my test. When I actually go to store some data eg:
dao.add(entity)
I get the dreaded "No API environment is registered for this thread."
Caused by: java.lang.NullPointerException: No API environment is registered for this thread.
at com.google.appengine.api.datastore.DatastoreApiHelper.getCurrentAppId(DatastoreApiHelper.java:108)
at com.google.appengine.api.datastore.DatastoreApiHelper.getCurrentAppIdNamespace(DatastoreApiHelper.java:118)
....
This is probably because my test case hasn't read in the GAE application-web.xml with the app details (although I'm guessing here I could really be wrong); so it doesn't know to write to the same datastore that the app running on the dev_server is reading/writing to.
How can I get my test to "point" to the same datastore as the app? Is there some "datasource" mechanism that I can inject both into the app and the test? Is there a way to get my test to force the datastore api to read the needed config?
Here is a page that talks about how to do unit tests that connect to a dev datastore. Is this the kind of thing you're looking for? Basically it talks about two classes, LocalServiceTestHelper and LocalDatastoreServiceTestConfig that you can use to set up an environment for testing. While the example given is for unit tests, I believe it will also work for your situation.
You can then configure things like whether the dev datastore is written to disk or just kept in memory (for faster tests). If you want this data to go to the same place as your dev server, you will probably want to adjust this, as I think the default is the "in memory" option. If you look at the javadoc there is a "setBackingStoreLocation" method where you can point to whatever file you want.
I've found the solution!!!!
For some reason the Namespace, AppID and the AuthDomain fields of the test datastore have to match that of the dev_server, then the dev_server can see the entities inserted by the test.
You can see the values for the environment (dev_server or test code) with the following statements
System.out.println(NamespaceManager.get());
System.out.println(ApiProxy.getCurrentEnvironment().getAppId());
System.out.println(ApiProxy.getCurrentEnvironment().getAuthDomain());
In your instance of LocalServiceTestHelper (eg: gaeHelper), you can set the values for the test environment
// the NamespaceManager is thread local.
NamespaceManager.set(NamespaceManager.getGoogleAppsNamespace());
gaeHelper.setEnvAppId(<the name of your app in appengine-web.xml>);
gaeHelper.setEnvAuthDomain("gmail.com");
Then the dev_server will see your entities. However because of synchronisation issues, if the test writes to the datastore after the dev_server has been started the dev_server wont see it unless it can be forced to reread the file (which I haven't figured out yet). Else the server has to be restarted.
I've found a workaround, although it's not very nice because each test method doesn't clean up the Datastore, as explained in the article Local Unit Testing for Java, however, the Datastore starts clean each time the Test class is run, so it's not so bad, provided that you're careful about that.
The problem is, that when using SpringJUnit4ClassRunner, the spring environment is created before the #Before annotation can be run, the solution is use #BeforeClass and use a static variable for LocalServiceTestHelper, to have them created before the Spring Environment is set up.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:META-INF/spring/context-test.xml")
#Transactional
public class MyTest {
#Inject
private MyService myService;
private static final LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());
#BeforeClass
public static void beforeClass() {
helper.setUp();
}
#AfterClass
public static void afterClass() {
helper.tearDown();
}
If anyone has a better solution, I'll be glad to hear!
All my unit test classes have been created by Visual Studio 2008 from a built-in unit test template that includes a "TestContext" property. So far I have not used a test context and this field is upsetting Resharper and code coverage.
Is it ok to remove TestContext or would doing that indicate my unit tests are poorly structured?
If you don't need it, remove it. You can always introduce it again afterwards. I've hardly used it too...
No harm in retaining the TestContext property, particularly if your unit test class makes use of data-driven test methods. Particularly useful if you use this type of statement:
Assert.AreEqual(myValue, this.TestContext.DataRow["ExpectedValue"].ToString())
Conversely, if you're using a hand-coded test class (i.e. not one generated by the VS "Add New Item" menu option), adding a property declaration as follows gives you instant access to the record of test data as it relates to the current unit test:
public TestContext TestContext { get; set; }
Hope that helps!