Skip to content

Commit 5812e7b

Browse files
authored
fix(config/test): provide a non-null halconfigDirectory in HalconfigParserMocker (#2172)
* test(config): validate spring config behavior with HalconfigDirectoryStructure to pave the way for some refactoring to support java 17 * refactor(config): use constructor injection in HalconfigParser as a general improvement and also to pave the way to cleanly specify a non-null halconfigDirectory during testing. * refactor(config): use constructor injection in HalconfigDirectoryStructure as a general improvement and also to pave the way to cleanly specify a non-null halconfigDirectory during testing. * fix(config/test): provide a non-null halconfigDirectory in HalconfigParserMocker since tests like this fail in java 17 otherwise: > Task :halyard-config:test AccountServiceSpec > load an existent account node FAILED java.lang.NullPointerException at java.base/java.util.Objects.requireNonNull(Objects.java:209) at java.base/sun.nio.fs.UnixFileSystem.getPath(UnixFileSystem.java:263) at java.base/java.nio.file.Path.of(Path.java:147) at java.base/java.nio.file.Paths.get(Paths.java:69) at com.netflix.spinnaker.halyard.config.config.v1.HalconfigDirectoryStructure.getHalconfigPath(HalconfigDirectoryStructure.java:50) at com.netflix.spinnaker.halyard.config.config.v1.HalconfigParser.transformHalconfig(HalconfigParser.java:159) at com.netflix.spinnaker.halyard.config.services.v1.HalconfigParserMocker.mockHalconfigParser(HalconfigParserMocker.groovy:38) at com.netflix.spinnaker.halyard.config.services.v1.AccountServiceSpec.makeAccountService(AccountServiceSpec.groovy:34) at com.netflix.spinnaker.halyard.config.services.v1.AccountServiceSpec.load an existent account node(AccountServiceSpec.groovy:56) * refactor(config): use RequiredArgsConstructor in HalconfigDirectoryStructure to reduce boilerplate
1 parent 532fff3 commit 5812e7b

File tree

6 files changed

+84
-13
lines changed

6 files changed

+84
-13
lines changed

halyard-config/halyard-config.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ dependencies {
4848
testImplementation 'org.junit.jupiter:junit-jupiter-api'
4949
testImplementation 'org.spockframework:spock-core'
5050
testImplementation 'org.springframework:spring-test'
51+
testImplementation 'org.springframework.boot:spring-boot-starter-test'
5152
testImplementation 'org.codehaus.groovy:groovy'
5253
testRuntimeOnly 'net.bytebuddy:byte-buddy'
5354
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'

halyard-config/src/main/java/com/netflix/spinnaker/halyard/config/config/v1/HalconfigDirectoryStructure.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,19 @@
2323
import java.io.File;
2424
import java.nio.file.Path;
2525
import java.nio.file.Paths;
26-
import lombok.Setter;
27-
import org.springframework.beans.factory.annotation.Autowired;
26+
import lombok.RequiredArgsConstructor;
2827
import org.springframework.stereotype.Component;
2928

3029
@Component
30+
@RequiredArgsConstructor
3131
public class HalconfigDirectoryStructure {
3232
private static ThreadLocal<String> directoryOverride = new ThreadLocal<>();
3333

3434
public static void setDirectoryOverride(String directory) {
3535
directoryOverride.set(directory);
3636
}
3737

38-
@Autowired @Setter String halconfigDirectory;
38+
private final String halconfigDirectory;
3939

4040
public String getHalconfigDirectory() {
4141
String directory = directoryOverride.get();

halyard-config/src/main/java/com/netflix/spinnaker/halyard/config/config/v1/HalconfigParser.java

+13-3
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,24 @@
6161
@Slf4j
6262
@Component
6363
public class HalconfigParser {
64-
@Autowired StrictObjectMapper objectMapper;
64+
private final StrictObjectMapper objectMapper;
6565

66-
@Autowired HalconfigDirectoryStructure halconfigDirectoryStructure;
66+
private final HalconfigDirectoryStructure halconfigDirectoryStructure;
6767

68-
@Autowired ApplicationContext applicationContext;
68+
private final ApplicationContext applicationContext;
6969

7070
private boolean useBackup = false;
7171

72+
@Autowired
73+
public HalconfigParser(
74+
StrictObjectMapper objectMapper,
75+
HalconfigDirectoryStructure halconfigDirectoryStructure,
76+
ApplicationContext applicationContext) {
77+
this.objectMapper = objectMapper;
78+
this.halconfigDirectoryStructure = halconfigDirectoryStructure;
79+
this.applicationContext = applicationContext;
80+
}
81+
7282
private Yaml getYamlParser() {
7383
return applicationContext.getBean(Yaml.class);
7484
}

halyard-config/src/test/groovy/com/netflix/spinnaker/halyard/config/config/v1/HalconfigParserSpec.groovy

+1-3
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,7 @@ class HalconfigParserSpec extends Specification {
3434
void setup() {
3535
ApplicationContext applicationContext = Stub(ApplicationContext.class)
3636
applicationContext.getBean(Yaml.class) >> new Yaml(new SafeConstructor())
37-
parser = new HalconfigParser()
38-
parser.applicationContext = applicationContext
39-
parser.objectMapper = new StrictObjectMapper()
37+
parser = new HalconfigParser(new StrictObjectMapper(), null /* halconfigDirectoyStructure */, applicationContext)
4038
}
4139

4240
void "Accept minimal config"() {

halyard-config/src/test/groovy/com/netflix/spinnaker/halyard/config/services/v1/HalconfigParserMocker.groovy

+10-4
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,18 @@ import java.nio.charset.StandardCharsets
2929

3030
class HalconfigParserMocker extends Specification {
3131
HalconfigParser mockHalconfigParser(String config) {
32-
def parserStub = new HalconfigParser()
3332
ApplicationContext applicationContext = Stub(ApplicationContext.class)
3433
applicationContext.getBean(Yaml.class) >> new Yaml(new SafeConstructor())
35-
parserStub.objectMapper = new StrictObjectMapper()
36-
parserStub.applicationContext = applicationContext
37-
parserStub.halconfigDirectoryStructure = new HalconfigDirectoryStructure();
34+
35+
// HalconfigDirectoryStructure needs a non-null halconfigDirectory for
36+
// Paths.get(getHalconfigDirectory()) to work properly. The directory
37+
// doesn't actually need to exist though. So, instead of
38+
//
39+
// String halconfigDirectory = Files.createTempDirectory("halyard-test")
40+
//
41+
// let's use an arbitrary string
42+
String halconfigDirectory = "halyard-test"
43+
def parserStub = new HalconfigParser(new StrictObjectMapper(), new HalconfigDirectoryStructure(halconfigDirectory), applicationContext)
3844

3945
def stream = new ByteArrayInputStream(config.getBytes(StandardCharsets.UTF_8))
4046
Halconfig halconfig = parserStub.parseHalconfig(stream)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2024 Salesforce, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License")
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.netflix.spinnaker.halyard.config.config.v1;
18+
19+
import static org.assertj.core.api.Assertions.assertThat;
20+
21+
import org.junit.jupiter.api.BeforeEach;
22+
import org.junit.jupiter.api.Test;
23+
import org.junit.jupiter.api.TestInfo;
24+
import org.springframework.boot.context.annotation.UserConfigurations;
25+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
26+
27+
class HalconfigConfigurationTest {
28+
29+
private final ApplicationContextRunner runner =
30+
new ApplicationContextRunner()
31+
.withConfiguration(
32+
UserConfigurations.of(ResourceConfig.class, HalconfigDirectoryStructure.class));
33+
34+
@BeforeEach
35+
void init(TestInfo testInfo) {
36+
System.out.println("--------------- Test " + testInfo.getDisplayName());
37+
}
38+
39+
@Test
40+
void testHalconfigDirectory() {
41+
runner.run(
42+
ctx -> {
43+
String homeDir = System.getProperty("user.home");
44+
assertThat(homeDir).isNotNull();
45+
46+
assertThat(ctx).hasSingleBean(HalconfigDirectoryStructure.class);
47+
String halconfigDirectory = ctx.getBean("halconfigDirectory", String.class);
48+
assertThat(halconfigDirectory).isNotNull();
49+
assertThat(halconfigDirectory).isEqualTo(homeDir + "/.hal");
50+
HalconfigDirectoryStructure halconfigDirectoyStructure =
51+
ctx.getBean(HalconfigDirectoryStructure.class);
52+
assertThat(halconfigDirectoyStructure.getHalconfigDirectory())
53+
.isEqualTo(halconfigDirectory);
54+
});
55+
}
56+
}

0 commit comments

Comments
 (0)