MsTest
Unit Testing
Test Automation
Setup Methods
Software Development

MsTest - executing method before each test in an assembly

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

In MSTest, there is an important lifecycle distinction between code that runs once per assembly and code that runs before each test method. MSTest gives you AssemblyInitialize for one-time setup and TestInitialize for per-test setup, but it does not provide a built-in assembly-wide "before every test in the assembly" hook. That limitation shapes how you structure shared setup logic.

The MSTest Lifecycle Hooks

MSTest provides several standard hooks:

  • 'AssemblyInitialize runs once before any tests in the assembly'
  • 'AssemblyCleanup runs once after all tests in the assembly'
  • 'ClassInitialize runs once before tests in one test class'
  • 'ClassCleanup runs once after tests in one test class'
  • 'TestInitialize runs before each test method in one class'
  • 'TestCleanup runs after each test method in one class'

A basic example looks like this:

csharp
1using Microsoft.VisualStudio.TestTools.UnitTesting;
2
3[TestClass]
4public class SampleTests
5{
6    [TestInitialize]
7    public void BeforeEachTest()
8    {
9        // Runs before every test method in this class.
10    }
11
12    [TestMethod]
13    public void TestOne() { }
14
15    [TestMethod]
16    public void TestTwo() { }
17}

This solves per-test setup inside one class, but not automatically across the whole assembly.

What MSTest Does Not Provide

There is no built-in MSTest attribute that means "run this method before every test in every class in the assembly."

That means if you need assembly-wide per-test behavior, you usually have to structure it yourself rather than relying on one special framework hook.

Common Workaround: Shared Base Class

A common pattern is to create a base test class with a TestInitialize method and inherit from it.

csharp
1using Microsoft.VisualStudio.TestTools.UnitTesting;
2
3public abstract class TestBase
4{
5    [TestInitialize]
6    public void BaseInitialize()
7    {
8        // Shared setup that should happen before each test.
9    }
10}
11
12[TestClass]
13public class FirstTests : TestBase
14{
15    [TestMethod]
16    public void TestA() { }
17}
18
19[TestClass]
20public class SecondTests : TestBase
21{
22    [TestMethod]
23    public void TestB() { }
24}

This is often the cleanest answer when you need the same before-each-test logic across many test classes.

Combining Assembly and Per-Test Setup

If you also need one-time assembly setup, combine AssemblyInitialize with per-test initialization.

csharp
1using Microsoft.VisualStudio.TestTools.UnitTesting;
2
3[TestClass]
4public static class AssemblyHooks
5{
6    [AssemblyInitialize]
7    public static void Init(TestContext context)
8    {
9        // One-time setup for the whole test assembly.
10    }
11}

Then keep per-test reset logic in TestInitialize, usually in a shared base class.

This division of responsibilities is important:

  • assembly hook for expensive shared startup
  • test hook for restoring clean state before each test

Why the Distinction Matters

People often ask for an assembly-wide before-each-test method because they want every test to begin with the same environment. That is a valid goal, but the framework still separates one-time lifecycle hooks from per-test lifecycle hooks.

Trying to force global per-test setup into AssemblyInitialize does not work because that method only runs once.

Alternatives for Shared Setup

Depending on the test design, alternatives include:

  • a shared base class
  • helper methods called from each class-level TestInitialize
  • custom test infrastructure outside MSTest lifecycle attributes

The best option depends on how much shared state the tests really need.

Common Pitfalls

The biggest mistake is expecting AssemblyInitialize to run before each test. It runs once per assembly, not once per method.

Another mistake is duplicating the same TestInitialize logic across many classes when a base class or helper would centralize it more cleanly.

People also confuse global configuration with per-test reset logic. One-time startup and before-each-test state reset are different responsibilities and should stay separate.

Finally, do not build overly global test setup if the tests can be made more isolated. Excessive shared lifecycle logic often hides test coupling.

Summary

  • MSTest does not provide a built-in assembly-wide before-each-test hook.
  • Use AssemblyInitialize for one-time setup and TestInitialize for per-test setup.
  • A shared base class is the usual way to apply the same TestInitialize logic across many test classes.
  • Keep one-time startup and per-test reset logic separate.
  • Prefer simple, explicit test isolation over overly global setup mechanisms.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.