현재 날짜에 따라 DB에서 가져온 데이터에 다른 논리를 구현하는 방법이 있습니다.단위 테스트 Java의 시간 기반 논리
단위 테스트에서 개체를 만들어서 DB에 저장하고 테스트 된 메서드를 호출하도록 테스트하고 싶습니다. 그러나 예측 가능한 결과를 얻으려면 매번 시스템 날짜를 변경해야하며 Java에서이를 수행하는 방법을 알지 못합니다.
제안 사항?
현재 날짜에 따라 DB에서 가져온 데이터에 다른 논리를 구현하는 방법이 있습니다.단위 테스트 Java의 시간 기반 논리
단위 테스트에서 개체를 만들어서 DB에 저장하고 테스트 된 메서드를 호출하도록 테스트하고 싶습니다. 그러나 예측 가능한 결과를 얻으려면 매번 시스템 날짜를 변경해야하며 Java에서이를 수행하는 방법을 알지 못합니다.
제안 사항?
현재 날짜를 사용하여 예상 결과를 생성 할 수 있습니다.
또는 시계를 사용하지 않고 테스트 한 시간을 사용하도록 시스템을 작성하십시오. 그러면 시간은 항상 예상되는 시간입니다.
I는 I 데이터는 예를 들어 구동 될 수 FixedTimeSource를 사용하여 테스트에서
interface TimeSource {
long currentTimeMS(); // actually I have currentTimeNS
void currentTimeMS(long currentTimeMS);
}
enum VanillaTimeSource implements TimeSource {
INSTANCE;
@Override
public long currentTimeMS() {
return System.currentTimeMillis();
}
@Override
public void currentTimeMS(long currentTimeMS) {
// ignored
}
}
class FixedTimeSource implements TimeSource {
private long currentTimeMS;
@Override
public long currentTimeMS() {
return currentTimeMS;
}
@Override
public void currentTimeMS(long currentTimeMS) {
this.currentTimeMS = currentTimeMS;
}
}
같은 것을 사용 입력/이벤트에 의해 설정됩니다. 프로덕션에서는 입력/이벤트의 시간을 무시하고 현재 시간을 사용하는 VanillaTimeSource.INSTANCE를 사용합니다.
첫 제안은 아마 이겼습니다. 일하지 마라. 또한 정확한 데이터를 가져 오는 것은 날짜를 기준으로 한 것입니다 (특정 열에 따라 다름). 이것은 논리가 다르지 않더라도 연중 거의 매일 다른 결과를 만들어야한다는 것을 의미합니다.아마도 두 번째 제안을 위해 갈 것입니다. – Alex
결과를 확인하기 전에 테스트 실행의 일부로 예상 결과를 생성 할 수 있습니다. 미리 생성 할 필요는 없습니다. –
실제로 시간을 매개 변수로받는 클래스/구성 요소를 만들면 시스템 시간과 분리되기 때문에 좋은 구성 요소임을 보장합니다. 모든 응용 프로그램 특정 구성 ("시스템 시간 사용")을 구성 요소 외부에 배치합니다. 외부 구성 가능한 자극에만 의존해야합니다. – helios
시간이 표시되는 방식을 사용자 정의 할 수 있도록 수업에 뭔가를 주입해야합니다.
예를
단위 테스트에서 지금public interface TimeProvider {
DateTime getCurrentTime();
}
public class UnderTest {
// Inject this in some way (e.g. provide it in the constructor)
private TimeProvider timeProvider;
public void MyMethod() {
if (timeProvider.getCurrentTime() == "1234") {
// Do something
}
}
}
위해 당신은 시간 제공자의 가짜 구현을 제공 할 수 있습니다. 실제 프로덕션 코드에서는 현재 날짜 시간 만 반환 할 수 있습니다.
물론, 'belgther'가 제안하는 것처럼 매개 변수로 제공 할 수도 있습니다 : –
나는 최근에 너무 많은 리팩터링을 할 수 없었던 비슷한 문제가 있었다. (시간 제약, 실수로 무언가를 부러 뜨리고 싶지 않았다.) 그것은 System.currentTimeMillis()를 호출 한 테스트 메소드를 가지고 있었고 테스트하려는 경우는 그 값이 리턴 한 값에 달려있었습니다. 같은 :
public class ClassINeedToTest {
public boolean doStuff() {
long l = System.currentTimeMillis();
// do some calculation based on l
// and return the calculation
}
}
는 단위 테스트를 허용하려면, 나는()는
protected long getCurrentTimeMillis() {
// only for unit-testing purposes
return System.currentTimeMillis();
}
보호 된 도우미 메서드를 가지고 있도록 클래스를 리팩토링이 방법은 doStuff에 의해 호출되었다. 이 기능을 변경하지만 지금은 단위 테스트를 호출 할 때, 그때 그러나 나는를 오염 한 것을 의미합니까
ClassINeedToTest testClass = new ClassINeedToTest() {
protected long getCurrentTimeMillis() {
// return specific date for my test
return 12456778L;
}
};
boolean result = testClass.doStuff();
// test result with an assert here
이를 같이 특정 값을 반환하는이 메소드를 오버라이드 (override) 할 수 있다는 것을 의미하지 않았다 인터페이스를 사용하여 비용이 너무 높다고 결정할 수 있습니다. 코드를 더 리팩토링 할 수 있다면 더 좋은 방법이있을 것입니다.
실제로 매개 변수로 시간을 제공하도록 메서드를 변경하면 원하는 시간을 지정하여 테스트 할 수 있습니다. 이것을 다시 말하는 것은 무엇입니까? – belgther
현재 날짜와 시간은 어떻게 받고 있습니까? 어쩌면 조롱은 작동 할 것입니다 ... –
지금은'new Date()'와 마찬가지로, 아마도 TimeProvider 클래스가 필요합니다. – Alex