An Old Man Tries Test-Driven Development

For a couple of years now, TDD just made sense to me, but it is just not a habit. I have a ton of green field coding coming up at work, so I wanted to try and get in the habit of working with a TDD mindset.

For my first attempt, I am coding a little service and front-end as I follow along with Josh and Mario’s Bootiful Testing presentation. I struggled to get the service contract bit working, so for now, I’ve commented that out. I’ll come back to it after doing some reading.

Spring Boot Starter

Start a new spring boot project with the following:

  • actuator
  • jpa
  • web
  • h2
  • lombok
  • cloud contract verifier

Entity

  • Write PortfolioTest
package com.hensen.toolbox.portfolio.service;

import org.assertj.core.api.Assertions;
import org.junit.Test;

public class PortfolioTest {

	@Test
	public void shouldConstructPortfolio() {

		Portfolio p = new Portfolio(1L, "TSLA", 100);
		Assertions.assertThat(p.getSymbol()).isEqualTo("TSLA");
	}
}
  • Write Portfolio
package com.hensen.toolbox.portfolio.service;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
public class Portfolio {

	@Id
	@GeneratedValue
	private Long id;
	private String symbol;
	private int shares;
}

Persisting Entity

  • Write Portfolio JPA Test
package com.hensen.toolbox.portfolio.service;

import org.assertj.core.api.Assertions;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.test.context.junit4.SpringRunner;

@DataJpaTest
@RunWith(SpringRunner.class)
public class PortfolioJpaTest {

	@Autowired
	private TestEntityManager testEntityManager;

	@Test
	public void shouldPersistViaJpa() {

		Portfolio p = this.testEntityManager.persistAndFlush(new Portfolio(null, "TSLA", 100));
		Assertions.assertThat(p.getId()).isNotNull();
		Assertions.assertThat(p.getSymbol()).isNotEmpty();
		Assertions.assertThat(p.getSymbol()).isEqualToIgnoringCase("TSLA");
		Assertions.assertThat(p.getShares()).isEqualTo(100);
	}

}
  • Write Portfolio Repository Test
package com.hensen.toolbox.portfolio.service;

import org.assertj.core.api.Assertions;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.junit4.SpringRunner;

@DataJpaTest
@RunWith(SpringRunner.class)
public class PortfolioRepositoryTest {

	@Autowired
	private PortfolioRepository repository;

	@Test
	public void shouldPersist() {

		Portfolio p = repository.save(new Portfolio(1L, "TSLA", 100));
		Assertions.assertThat(p.getId()).isNotNull();
		Assertions.assertThat(p.getSymbol()).isEqualToIgnoringCase("TSLA");
		Assertions.assertThat(p.getShares()).isEqualTo(100);
	}
}
  • Write Portfolio Repository
package com.hensen.toolbox.portfolio.service;

import org.springframework.data.jpa.repository.JpaRepository;

public interface PortfolioRepository extends JpaRepository<Portfolio, Long> {

}

Controller

  • Write Portfolio Rest Controller Test
package com.hensen.toolbox.portfolio.service;

import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import java.util.Collections;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.context.junit4.SpringRunner;

@WebMvcTest
@RunWith(SpringRunner.class)
public class PortfolioRestControllerTest {

	@MockBean
	private PortfolioRepository portfolioRepository;

	@Autowired
	private MockMvc mvc;

	@Test
	public void givenHttpRequest_whenGetPortfolio_thenAllPortfoliosReturned() throws Exception {

		Mockito.when(this.portfolioRepository.findAll())
				.thenReturn(Collections.singletonList(new Portfolio(null, "TSLA", 100)));

		this.mvc.perform(MockMvcRequestBuilders.get("/portfolios"))
				.andExpect(status().isOk())
				.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
				.andExpect(jsonPath("@.[0].symbol").value("TSLA"));
	}
}
  • Write Portfolio Rest Controller
package com.hensen.toolbox.portfolio.service;

import java.util.Collection;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PortfolioRestController {

	private final PortfolioRepository portfolioRepository;

	public PortfolioRestController(PortfolioRepository portfolioRepository) {
		this.portfolioRepository = portfolioRepository;
	}

	@GetMapping("/portfolios")
	Collection<Portfolio> portfolios() {
		return portfolioRepository.findAll();
	}
}

My source code

Github: portfolio-service
Github: portfolio (just a stub to verify an http get request)