Skip to content

Commit 10684ba

Browse files
Merge pull request diffblue#524 from diffblue/bugfix/autowired-fields-not-properties
Fix bug where autowired fields were set using property accessors
2 parents 1737d9d + 957f8c3 commit 10684ba

File tree

4 files changed

+43
-4
lines changed

4 files changed

+43
-4
lines changed

env-model-generator/src/annotationConfig.ts

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface AutoWiredFields {
1818

1919
export interface AutoWiredField {
2020
type: string;
21+
isPublic: boolean;
2122
}
2223

2324
export interface Configurations {

env-model-generator/src/model.ts

+37-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
Method,
1414
Null,
1515
Return,
16+
Statement,
1617
StringConstant,
1718
Symbol,
1819
} from "./javaCode";
@@ -23,6 +24,8 @@ import { makeIdentifier, upperInitialChar } from "./utils";
2324
export interface BeanProperty {
2425
name: string;
2526
value: Value;
27+
isPublic: boolean;
28+
isField: boolean;
2629
}
2730

2831
interface Factory {
@@ -117,17 +120,49 @@ export class Bean implements IBean {
117120
this._exceptions = [];
118121
const variableName = !this.isLazyInit ? `_${this.identifier}` : "value";
119122
const [ constructorArgs, constructorArgsExceptions ] = collectionToJava(this.constructorArgs);
120-
const [ initialisers, initialisersExceptions ]: [ FnStatement[], string[][] ] =
123+
const [ initialisersStatements, initialisersExceptions ]: [ Statement[][], string[][] ] =
121124
this.properties.size === 0
122125
? [ [], [] ]
123126
: <any>_.unzip([...this.properties].map((property) => {
124127
const [ initialiserJava, initialiserExceptions ] = property.value.toJava();
128+
let statements: Statement[];
129+
if (property.isField) {
130+
if (property.isPublic)
131+
statements = [ new Assignment(`${variableName}.${property.name}`, initialiserJava) ];
132+
else {
133+
const fieldVariableName = `${property.name}_field`;
134+
statements = [
135+
new Declaration(
136+
"java.lang.reflect.Field",
137+
fieldVariableName,
138+
new FnCall(`${variableName}.getClass().getDeclaredField`, [ new StringConstant(property.name) ])),
139+
new FnStatement(new FnCall(`${fieldVariableName}.setAccessible`, [ new Symbol("true") ])),
140+
new FnStatement(new FnCall(`${fieldVariableName}.set`, [ new Symbol(variableName), initialiserJava ])),
141+
];
142+
}
143+
} else {
144+
const setterName = `set${upperInitialChar(property.name)}`;
145+
if (property.isPublic)
146+
statements = [ new FnStatement(new FnCall(`${variableName}.${setterName}`, [ initialiserJava ])) ];
147+
else {
148+
const setterVariableName = `${property.name}_setter`;
149+
statements = [
150+
new Declaration(
151+
"java.lang.reflect.Method",
152+
setterVariableName,
153+
new FnCall(`${variableName}.getClass().getDeclaredMethod`, [ new StringConstant(setterName) ])),
154+
new FnStatement(new FnCall(`${setterVariableName}.setAccessible`, [ new Symbol("true") ])),
155+
new FnStatement(new FnCall(`${setterVariableName}.invoke`, [ new Symbol(variableName), initialiserJava ])),
156+
];
157+
}
158+
}
125159
return [
126-
new FnStatement(new FnCall(`${variableName}.set${upperInitialChar(property.name)}`, [ initialiserJava ])),
160+
statements,
127161
initialiserExceptions,
128162
];
129163
}));
130164
this._exceptions = _.uniq(constructorArgsExceptions.concat(_.flatten(initialisersExceptions)));
165+
const initialisers = _.flatten(initialisersStatements);
131166
if (this.initMethod !== undefined)
132167
initialisers.push(new FnStatement(new FnCall(`${variableName}.${this.initMethod}`, [])));
133168
let typeName;

env-model-generator/src/parseJson.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,12 @@ function parseJsonComponent(id: string, namedBean: NamedComponent): model.IBean
145145
for (const fieldName in component.fields) {
146146
if (!component.fields.hasOwnProperty(fieldName))
147147
continue;
148+
const field = component.fields[fieldName];
148149
properties.push({
149150
name: fieldName,
150-
value: getBeanForClass(component.fields[fieldName].type, `Auto-wired field '${namedBean.qualifiedClassName}.${fieldName}'`),
151+
value: getBeanForClass(field.type, `Auto-wired field '${namedBean.qualifiedClassName}.${fieldName}'`),
152+
isField: true,
153+
isPublic: field.isPublic,
151154
});
152155
}
153156
// TODO: Handle constructor arguments

env-model-generator/src/parseSpringXml.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ function parseXmlBean(id: string | undefined, bean: spring.BeanType): model.IBea
121121
return parseProperty(arg);
122122
});
123123
const properties = (bean.property || []).map((property) =>
124-
({ name: property.name, value: parseProperty(property) }));
124+
({ name: property.name, value: parseProperty(property), isField: false, isPublic: true }));
125125
let impl;
126126
if (factoryBean && bean.factoryMethod)
127127
impl = { bean: factoryBean, method: bean.factoryMethod };

0 commit comments

Comments
 (0)