37
Unit Testing in .NET

Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

  • Upload
    lyngoc

  • View
    215

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Unit Testing in .NET

Page 2: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Philosophy of Unit Testing

• What?

• Where?

• Why?

• How?

• What it is not?

Page 3: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

• Test individual components (units)

• in isolation

• to confirm preexisting specification.

• Inputs … -> expected results

• Test functions, methods.

• Use a framework to make it easier (xUnit or ?Unit)

isolate and validate

verify

Page 4: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

• Write tests after creating specification, but before implementing methods.

• Best if written by the developer or the development team. Why?

• Test-driven development

• Supports regression testing

Page 5: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

The Art of Unit Testing, by R Osherov

Page 6: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->
Page 7: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Assertions

http://junit.sourceforge.net/javadoc/org/junit/Assert.html

JUnit

assertEquals() assertFalse() assertNotNull() assertNotSame() assertNull() assertSame() …

By the way, you should use assertions in everyday programming

Java: assert i > 0; C#: Debug.Assert( i > 0 ); Python: assert i > 0

Page 8: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Unit Assertions

Classic ModelAssert.isEmpty() Assert.areEqual() Assert.Null() Assert.notNull() …

https://github.com/nunit/docs/wiki/Classic-Modelhttps://github.com/nunit/docs/wiki/Constraint-Model

Page 9: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Good Habits• Try to make tests independent or orthogonal to other tests

• Test only one code unit at a time

• Don’t name your tests: test0, test1, …

• Use setup and teardown to create a clean environment for each test

• Don’t have unit tests access your database — use fake data (write a “mock” object that meets the same interface) ==> break dependencies

• Refactor to make your code more testable

• Discover a flaw at the component level? Write unit tests first to expose it (reproduce it). Then fix the error.

• Run tests prior to committing (or merging) your code

Page 10: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Start Simple• Test methods with no dependencies

• Make sure constructor doesn’t have dependencies

input Method output

Page 11: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Find something to test

public ActionResult ChangeLoginName(string oldName, string newName) { User user = repository.FetchByLoginName(oldName); user.LoginName = newName; repository.SubmitChanges(); // render some view to show the result return View(); }

Page 12: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Arrange — Act — Assert• Arrange

Set up for the test. Configure the system one way or another. Must be able to do this.

• Act

Execute or invoke something, with some input, to obtain some output. Must be able to do this.

• Assert

Usually the easy part.

Page 13: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Run Tests: Test -> Run -> All Tests

Page 14: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Unit Testing Demo

Page 15: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Harder

input

Function

output

Database

Internet

Page 16: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Not Unit Testable

Page 17: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Why Not?

• “Uncontrolled” dependencies

• All or most functionality in 1 method, with no separation and no “control” over it

• Code is doing more than 1 thing

Page 18: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

SOLID• Single responsibility principle

a class (module, method or function) should do one thing and one thing only

• Open/closed principle

• Liskov substitution principle it should be possible to substitute in fakes, stubs or mocks without fundamentally changing anything

• Interface segregation principle create segregation of responsibilities and become agnostic of implementors by replacing concrete classes with interfaces (having the minimum of functionality required)

• Dependency inversion principle (and Inversion of Control) invert the “high-level module depends on low-level module” pattern. Break direct dependencies by using dependency injection pattern and providers.

https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)

Page 19: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

The Art of Unit Testing, by R Osherov

Page 20: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->
Page 21: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->
Page 22: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->
Page 23: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->
Page 24: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->
Page 25: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Problem?

Just a stub for now

Page 26: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

One Solution: inject via

constructor

will be other logic here, i.e. test the name not just the extension

Page 27: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->
Page 28: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->
Page 29: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

• Up Next …

• Testing code that reads/writes to a database

• Use a “mocking framework” to make it easier, i.e.

• Moq: https://github.com/Moq/moq4

• Use [SetUp] and [TearDown] to seed your mock object

Page 30: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Controller

DbContext

EntityFramework

Database

Default Setup

Page 31: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Controller

DbContext

EntityFramework

Database

Using Repository Pattern

ActualRepoForTestingRepo

ISomethingRepository

An interface

Page 32: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Need to modify to allow constructor

injection

Page 33: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Inject mock object

Page 34: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Sports Store Example from

Entity - Single table

Page 35: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Break dependency with Repository pattern

Page 36: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

pagination

constructor injection

Page 37: Unit Testing in - wou.edumorganb/lecture/SP19UnitTesting.pdf · •Test individual components (units) • in isolation • to confirm preexisting specification. • Inputs … ->

Unit Test Pagination